如果在主脚本中嵌入多处理.Process,则poll将不会返回相同的结果

时间:2013-09-18 00:12:13

标签: python-3.x subprocess multiprocessing

我想以非阻塞的方式读取外部程序的输出与我的python代码同时运行。要启动程序(例如netcat),我使用subprocess.Popen并将其stdout和stderr绑定到subprocess.PIPE。然后我启动了一个multiprocessing.Process,其任务是检查该程序是否仍在运行(proc.poll()),如果是,它会尝试从其管道中读取。我的问题是“proc.poll()”总是在“listen_to_fds”函数中返回0但在“call”函数(这是主函数)中运行得非常好,即proc.poll()返回None(应用程序)我启动永远不会完成,所以这是正确的返回值。)

我用以下函数调用以下函数:      call(“./ test.sh”)

我的模块

def listen_to_fds(logger,proc):
  while proc.poll() is None:
    print("program still running", proc.returncode)
    data = proc.stdout.read()
    if data:
        print("Data", data)
    time.sleep(1)

print("last check", proc.returncode )



def call(cli ):

logger = logging.getLogger("isix.daemon")
cli_args = shlex.split(cli)

proc = subprocess.Popen(
        cli_args
        ,stdout=subprocess.PIPE 
        ,stderr=subprocess.PIPE
        )


set_fd_as_nonblocking( proc.stdout )
set_fd_as_nonblocking( proc.stderr )

pipe2 = multiprocessing.Process( 
    target=listen_to_fds,
    args=( logger, proc )
    )
while proc.poll() is None:
   print("program still running", proc.returncode)
   data = proc.stdout.read()
   if data:
         print("Data", data)
   time.sleep(1)

1 个答案:

答案 0 :(得分:0)

子进程poll函数使用操作系统的wait调用(在非阻塞模式下,通常为wait4),这要求执行“等待”的进程是进程的父进程等待着。

您不能在直接父级之外的任何其他地方收集返回代码,但是可以通过使用{{1}发送信号0(零)来检查任何进程是否存在}。如果允许您发送信号,并且该过程存在,os.kill成功(不影响其他过程)。如果您不允许发送信号(该流程已存在但属于其他用户),则os.kill(pid, 0)会将os.kill(pid, 0)OSError一起提升为EPERM。如果该流程不再存在,则errno会将os.kill(pid, 0)OSError一起提升为ESRCH。 (如果进程在您不查看时完成,则会出现“不良窗口”,然后该进程的父进程收集它,使进程ID可供重用,然后您的相同用户ID启动一个新的,获取相同进程ID的不相关进程,但进程ID不会非常快速地回收,因此这不太可能。)

但总的来说,最好采用其他方法,例如使用errnoselect或类似方法来决定何时读取数据。