Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/348.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python lib psutil:如何使用wait()获取退出状态_Python_Subprocess_Exit Code - Fatal编程技术网

Python lib psutil:如何使用wait()获取退出状态

Python lib psutil:如何使用wait()获取退出状态,python,subprocess,exit-code,Python,Subprocess,Exit Code,我正在使用带有许多参数的子流程Popen执行第三方应用程序 myprocess=Popen(['executionlist','with','arguments'],stdout=PIPE,stderr=PIPE) myprocess.communicate() 获取我的stdout和err元组,第三方应用程序在后台启动,因此我在stdout中获取其pid…[如果我尝试在forground中运行,它会抛出“错误打开终端:未知”] 我正在使用psutil跟踪所有这些分叉,并使用 EXITCODE

我正在使用带有许多参数的子流程Popen执行第三方应用程序

myprocess=Popen(['executionlist','with','arguments'],stdout=PIPE,stderr=PIPE)
myprocess.communicate()
获取我的stdout和err元组,第三方应用程序在后台启动,因此我在stdout中获取其pid…[如果我尝试在forground中运行,它会抛出“错误打开终端:未知”] 我正在使用psutil跟踪所有这些分叉,并使用

EXITCODE=psutil_obj.wait(timeout=xxx)
应用程序发送不同的退出代码,我需要在EXITCODE中访问这些代码,但当我在不同的python脚本中运行它时,它总是给我“无”值

根据,, 等待()进程终止,如果进程是当前进程的子进程,则返回退出代码,否则无


我是否可以从独立的进程id访问退出代码,而不是由Popen专门分叉?

您引用的文档直接告诉您,
psutil
只能获取退出代码“如果该进程是当前进程的子进程”

这才是真正的关键所在——这不是流程是否由
Popen
启动,而是它是否是当前流程的子流程*

这是Unix进程模型的基础。父母必须等待他们的孩子。你不能让其他人等他们(除非重新租用)。如果父级仍在运行,则必须由它来收获它们。如果父级不再运行,则子级可能已经是一个僵尸,或者它被重新出租给父级的父级或init/launchd/等,或者成为孤儿(在不同的系统和不同的情况下,细节是不同的)。没有其他进程可以等待它们的情况

最重要的是,一旦父进程调用
wait
(这是
Popen.communicate
所做的),进程及其在系统进程表中的条目及其retcode可能不再存在



*也就是说,即使您没有跨进程,将
子进程
与较低级别的API(如
os
psutil
)混合使用也不是一个好主意。如果创建
Popen
对象,则必须调用其
wait
方法,或者调用其他类似于
通信的方法。一旦你这么做了,它可能就不存在了。如果要使用
os.wait
,请使用由
os
中的fork/spawn/etc.方法创建的进程。如果要使用
psutil.wait
,可以使用由
os
psutil.Popen
创建的进程,但不能使用
子进程。Popen

引用的文档直接告诉您,
psutil
只能获取退出代码“如果该进程是当前进程的子进程”

这才是真正的关键所在——这不是流程是否由
Popen
启动,而是它是否是当前流程的子流程*

这是Unix进程模型的基础。父母必须等待他们的孩子。你不能让其他人等他们(除非重新租用)。如果父级仍在运行,则必须由它来收获它们。如果父级不再运行,则子级可能已经是一个僵尸,或者它被重新出租给父级的父级或init/launchd/等,或者成为孤儿(在不同的系统和不同的情况下,细节是不同的)。没有其他进程可以等待它们的情况

最重要的是,一旦父进程调用
wait
(这是
Popen.communicate
所做的),进程及其在系统进程表中的条目及其retcode可能不再存在



*也就是说,即使您没有跨进程,将
子进程
与较低级别的API(如
os
psutil
)混合使用也不是一个好主意。如果创建
Popen
对象,则必须调用其
wait
方法,或者调用其他类似于
通信的方法。一旦你这么做了,它可能就不存在了。如果要使用
os.wait
,请使用由
os
中的fork/spawn/etc.方法创建的进程。如果要使用
psutil.wait
,可以使用由
os
psutil.Popen
创建的进程,但不能使用
subprocess.Popen

在来回查看一些注释后,我怀疑您实际上是想做这样的事情:

在您的主程序中,“启动并忘记”一些后台进程。但稍后,在同一个程序中,每当这些进程实际完成时,运行一些代码来访问进程的返回代码(可能还有输出)


下面是一个这样做的示例,通过为每个后台进程使用一个观察线程:

import subprocess
import threading

def doit(arglist, callback):
    def threadfunc():
        p = subprocess.Popen(arglist, 
                             stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        out, err = p.communicate()
        callback(out, err, p.returncode)
    t = threading.Thread(target=threadfunc)
    t.start()

这有两个明显的局限性,但最终它们与您在尝试(例如,同时通过internet与多台机器进行通信)时处理的多路复用问题完全相同,并且它们具有相同的解决方案

首先,拥有数百个线程是不好的。它们没有做任何事情,但它们仍然有大堆栈,占用了虚拟内存空间(在32位Python中尤其糟糕),并占用了内核调度程序表中的空间(在旧的Unix中尤其糟糕)。幸运的是,如果您不关心Windows,您可以使用与处理网络代码相同的方法来解决这一问题:将子流程管道放入
select
poll
循环中。或者,如果您确实关心Windows,或者只是不想编写自己的
select
loop,那么请找到一个可以为您完成所有繁重工作的框架。如果您将找到一些特定于
子流程的选项
。如果您已经在使用事件驱动的网络或GUI框架,如Twisted或Qt,它很可能有自己的内置方式(例如,请参阅Twisted)

其次,您的
回调
在某个任意后台线程中被调用,无法将返回值或异常传播到c语言的其余部分