在后台冻结stdin,在前台解冻

2024-05-15 05:09:06 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图在后台运行一个sript:

nohup script.py > out 2> err < /dev/null &

脚本(Python 3.4)在某个时候会:

^{pr2}$

(它有一个菜单在其中一个线程中运行)

nohup的电话崩溃了:

EOFError: EOF when reading a line

因为/dev/null重定向stdin我想。如果我在没有stdin重定向的情况下运行它:

nohup script.py > out 2> err &

它会崩溃:

OSError: [Errno 9] Bad file descriptor

如果我使用:

script.py > out 2> err

它可以工作,但是阻塞了我的终端(它在前台)

如果我使用:

script.py > out 2> err &

它可以在后台运行,但只要input调用到达,它就会停止。在

我想要的是:

  • 能够将stdoutstderr重定向到文件系统
  • 能够将脚本放在背景中
  • 能够将if移到前台并与菜单正常交互(因此stdin必须以某种方式启用)。stdout和{}仍将重定向到文件系统,但{}将正常工作。在
  • 脚本必须在后台和前台运行良好(当然,菜单在后台不工作,因为stdin是“冻结的”)

基本上,我想要的是当它在后台时,stdin有点“冻结”,每当它出现在前台时,它又能正常工作。在

这可能吗?解决方案不需要涉及nohup


Tags: pydev脚本stdinstdout菜单scriptout
1条回答
网友
1楼 · 发布于 2024-05-15 05:09:06

您想要的(以及在python下input是如何工作并在EOF上失败)的交互式菜单意味着您在调用程序时无法安全地将文件作为stdin传递。这意味着您唯一的选择是这样调用:

$ script.py > out 2> err &

作为示范,这是我的脚本:

^{pr2}$

本质上,它每秒钟都会写入stdout,每两秒钟它就会写入stderr,最后,每隔10秒它就会等待输入。如果我运行这个程序并等待一秒钟(以允许磁盘刷新),然后将其链接在一起,如下所示:

$ python script.py > out 2> err & sleep 2.5; cat out err
[1] 32123
1000
2000
2000
$ 

请至少等待10秒,然后再次尝试cat out err

$ cat out err
1000
2000
3000
4000
5000
6000
7000
8000
9000
10000
? 2000
4000
6000
8000
10000

[1]+  Stopped                 python script.py > out 2> err
$ 

请注意,input生成的提示也被写入stdout,程序有效地继续运行到它期望stdin给它数据的地方。您只需通过%将进程恢复到前台,并开始向它提供所需的数据,然后使用^ZCtrlZ)暂停,并使用%&在后台继续运行。示例:

$ %
python script.py > out 2> err
Test input
^Z
[1]+  Stopped                 python script.py > out 2> err
$ %&
[1]+ python script.py > out 2> err &
$

再次等待10秒后,cat out

$ cat out
1000
...
10000
? The answer is Test input
11000
...
20000
? 
[1]+  Stopped                 python script.py > out 2> err
$

这实际上是一个基本的速成课程,教你如何在前台和后台运行标准进程,如果代码正确地处理标准IO,事情就会如预期的那样工作。在

最后,你不可能真的同时拥有。如果应用程序需要stdin而没有提供,那么clear选项是failure。但,若提供了一个应用程序,但应用程序被发送到后台并继续运行,则它将是Stopped,因为它期望进一步的输入。如果这个停止的行为是不需要的,那么应用程序就是有问题的,那么除了更改应用程序使其在以/dev/null作为其stdin执行时遇到{}时不会导致错误。如果您想让stdin保持原样,那么当应用程序在后台时,它能够以某种方式保持运行,那么就不能使用input函数,因为当{}为空时,它将阻塞(导致进程停止)。在


既然您已经通过下面的注释澄清了您的“交互式提示”是在一个线程中运行的,并且由于input的用法直接从stdin读取,而且您似乎不愿意修改您的程序(您要求的是一般情况),但希望一个实用程序为您完成这项工作,简单的解决方案是在^{}^{}会话中执行此操作,因为它们完全实现了一个伪tty,它独立于启动的任何控制台(因此您可以断开连接并将会话发送到后台,或启动其他虚拟会话,请参阅手册页),这将提供程序所需的stdio。在

最后,如果您真的希望您的应用程序本机支持这一点,您不能简单地按原样使用input,但是您应该检查是否可以安全地调用input(例如,可能使用^{}),或者通过检查进程当前是在前台还是后台(您可以从How to detect if python script is being run as a background process开始工作)您可能希望使用sys.stdin进行检查,以确定是否可以安全地调用input(但是,如果用户在输入时挂起任务,它仍将挂起为input等待),或者使用unix套接字进行通信。在

相关问题 更多 >

    热门问题