我想以非阻塞的方式读取外部程序的输出与我的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)
答案 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不会非常快速地回收,因此这不太可能。)
但总的来说,最好采用其他方法,例如使用errno
或select
或类似方法来决定何时读取数据。