我在Unix工作,我有一个"通用工具"在后台加载另一个进程(GUI实用程序),然后退出。
我打电话给我的"通用工具"从Python脚本,使用 Popen 和proc.communicate()
方法。
我的"通用工具"运行约1秒钟,在后台加载GUI进程 并立即退出。
问题是proc.communicate()
继续等待该过程,尽管它已经终止。我必须手动关闭GUI(这是在BG上运行的子进程),因此proc.communicate()
返回。
如何解决这个问题?
主进程终止后我需要proc.communicate()
返回,而不是等待在后台运行的子进程...
感谢!!!
添加一些代码段:
我的"常规工具"最后的主线(用Perl编写):
if ($args->{"gui"}) {
my $script_abs_path = abs_path($0);
my $script_dir = dirname($script_abs_path);
my $gui_util_path = $script_dir . "/bgutil";
system("$gui_util_path $args->{'work_area'} &");
}
return 0;
我的Python脚本运行"常规工具" :
cmd = PATH_TO_MY_GENERAL_TOOL
proc = subprocess.Popen(cmd, shell = True, stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
stdout, dummy = proc.communicate()
exit_code = proc.returncode
if exit_code != 0:
print 'The tool has failed with status: {0}. Error message is:\n{1}'.format(exit_code, stdout)
sys.exit(1)
print 'This line is printed only when the GUI process is terminated...'
答案 0 :(得分:1)
请勿使用communicate
。 Communicate明确设计为等待进程的stdout关闭。据推测,perl并没有关闭stdout,因为它正在打开它自己的子进程来写入。
您也不需要使用Popen
,因为您并未真正使用其功能。也就是说,您创建管道,然后使用您自己的消息重新打印到stdout。而且看起来你根本不需要外壳。
尝试使用subprocess.call
甚至subprocess.check_call
。
例如
subprocess.check_call(cmd)
如果进程返回非零退出代码,则无需检查返回值,因为check_call
会抛出异常(包含退出代码)。该过程的输出直接写入控制终端 - 无需重定向输出。
最后,如果cmd
是可执行文件及其参数的路径的组合,则使用shlex.split
。
例如
cmd = "echo whoop" # or cmd = "ls 'does not exist'"
subprocess.check_call(shlex.split(cmd))
要测试的示例代码:
mypython.py
import subprocess, shlex
subprocess.check_call(shlex.split("perl myperl.pl"))
print("finishing top level process")
myperl.pl
print "starting perl subprocess\n";
my $cmd = 'python -c "
import time
print(\'starting python subprocess\')
time.sleep(3);
print(\'finishing python subprocess\')
" &';
system($cmd);
print "finishing perl subprocess\n";
输出是:
$ python mypython.py
starting perl subprocess
finishing perl subprocess
finishing top level process
$ starting python subprocess
finishing python subprocess