2010-10-11 17 views
5

我很难从python子进程模块中获得我想要的东西(应该是统一/平台无关的抽象,afaik,但不要让我开始吧:))。python subprocess with shell = True:重定向和平台无关的子进程查杀

所以我简单的事情是以下。我想

  • 启动外部(标准输入输出)应用程序(可能具有子过程),其中,我使用壳式重定向(如“./myapp> stdout_log> stderr_log”)
    • 基本上我想执行shell命令行,所以我必须指定壳=真为subprocess.Popen()(或者在命令行重定向将不会工作)
  • 我想发动这个命令行以异步的方式(所以它作为一个独立的子进程运行,但我的python proc ess不会等待它完成)
  • (我的父级python进程会不时地查看子进程的日志以提取信息,但这与问题无关)
  • 如果我的父级python进程决定,它应该能够终止这个子进程。

现在,我的主要问题是

  • 我基本上被迫使用壳=真,得到重定向工作
  • 父蟒蛇处理孩子的标准输出/标准错误进程不是一个选项,因为我找不到以非等待方式执行的功能(并且父级python进程必须在孩子运行时做其他事情)
  • 如果我使用壳=真然后subprocess.kill()将只终止
  • 我需要的是在任何平台上工作的可靠的子进程的终止方法(但至少Linux和Windows)
壳而不是子进程

我希望我足够具体。感谢提前任何提示/提示 - 我只是花了一整天的子过程,恕我直言它是 痛苦 远离平台无关或简单:(但也许它只是我)

更新(2010年-10-13):

如果启动一个子进程(即使外壳= FALSE),那么subprocess.Popen.kill()函数将只杀死子进程(所以,如果有任何“孙子“流程,他们不会被终止)

我读到有关使用preexec_fn参数设置所有的子进程的SID,但它仅限Unix:timeout a subprocess

+0

相关:[如何终止与shell = True启动的python子进程](http://stackoverflow.com/q/4789837/95735) – 2012-10-18 23:11:15

回答

4

上次我遇到类似的情况时,我发现最简单的(实际上唯一的)解决方案是启动一个线程来处理您的子进程。你可以用这种方法采用不同的路线,分析shell风格的命令的管道,并在python代码中执行这些命令(你说因阻塞而不是选项),这将同时修复杀死问题。基本上,线程封装似乎是要走的路。

令人遗憾的是我的经验与subprocess都在Windows平台上,它有很多自己的小怪癖。 subprocess看起来有很多缺陷,尽管考虑到它应该替代的popen,popen2等模块的存在,它必须做好工作。

+0

是的,我可能走线程的方式,因为我不觉得像在这条路上浪费更多时间......感谢提示。如果这是任何安慰,linux上的子进程也有它自己的怪癖。 :( – riviera 2010-10-12 08:34:12

2

通过你的问题,一次一个状况:

我基本上被迫使用shell =真,得到重定向工作

你不能只使用stdoutstderr参数?

out_log = open("stdout_log", "w") 
err_log = open("stderr_log", "w") 
subproc = subprocess.popen(..., stdout=out_log, stderr=err_log, ...) 

处理孩子的标准输出/标准错误在父Python进程是不是一种选择,因为我无法在非等待的方式做它找到的功能(与父蟒蛇过程中必须做其他而孩子正在运行的东西)

这是因为Windows。在Unix类型的操作系统上,您只需使用select模块。 Windows只能在套接字上使用select,而不是文件。

如果我使用shell =真然后subprocess.kill()将只终止外壳,但不是孩子的过程

因为当shell=True子进程,并命令它的孩子。

我需要在任何平台上工作(但至少Linux和Windows)

是否可靠的子进程的终止方法甚至还存在一个用于Windows的可靠的子进程的终止方法?最后我听说,即使任务管理器的结束任务也不是100%可靠的。而在Linux中,您可能无法杀死一个通过崩溃的驱动程序打开文件的进程。

就像斯蒂格玛说的,对于Windows支持,您需要使用线程作为子进程代理。此外,您应该尝试使用shell=False运行,如果不能,请详细说明为什么不。

+0

“因为then shell = True shell是子进程,而命令是它的子进程。” - 这是正确的,我意识到这一点,但我期望process _hierarchy_ termination(或至少一个选项如果子进程应该是一个'高级',独立于平台的模块,恕我直言,这将是预期的行为。 – riviera 2010-10-12 08:35:26

3

回答一些问题:

3

我也曾经有过类似的情况在最近,我创建了一个使用shell=True,后来又杀死它需要一个Python子。然而,由于shell参数,“真实”过程是shell的子进程,即主进程的孙子。杀死儿童外壳不会自动杀死孙子。

在我的顶级python脚本:

childProcess = subprocess.Popen('python other.py', shell=True) 

杀壳和“真正的工作”孙子,我这样做:

subprocess.call("ps -ef | awk '$3 == \"" + str(childProcess.pid) + "\" {print $2}' | xargs kill -9", shell=True) 
childProcess.kill() 

第一行会杀死所有儿童子进程(根据ps -ef亲子关系,第二行杀死孩子

有趣的是,在Ubuntu上这是必需的,但在Mac OSX上并不是必须的,因为o在Mac上,孙子似乎接管了原来的子shell进程ID。