Python失去了对子过程的控制



我正在使用使用Python作为其脚本API的一部分的商业应用程序。提供的功能之一就是称为App.run()。当调用此功能时,它将启动一个新的Java进程,该进程完成其余的执行。(不幸的是,由于提供的Python模块是.pyc文件,我真的不知道它在引擎盖下做什么,而且许多Python函数都是SWIG生成的)。

我遇到的问题是,我正在将App.run()调用构建到一个较大的Python应用程序中,该应用程序需要执行一些保证的清理代码(关闭数据库等)。不幸的是,如果子过程被 ctrl c 中断,则它中断并返回命令行而无需返回控件到主Python程序。因此,我的清理代码永远不会执行。

到目前为止,我已经尝试过:

  1. 在Atexit上注册功能...不起作用
  2. 将清理放入__del__ destructor类中...不起作用。(App.run()在同类中)
  3. ctrl c 创建一个信号处理程序。
  4. App.run()放入线程中... ctrl c
  5. 后导致内存故障
  6. App.run()放入过程(来自多处理)...不起作用

有什么想法会发生什么?

这只是一个轮廓 - 但是类似的东西?

import os
cpid = os.fork()
if not cpid:
    # change stdio handles etc
    os.setsid() # Probably not needed
    App.run()
    os._exit(0)
os.waitpid(cpid)
# clean up here

(os.fork仅 *nix)

可以用subprocess以操作系统的方式实现相同的想法。这个想法是在儿童过程中运行App.run(),然后等待儿童进程退出;不管孩子的过程如何死亡。在Posix上,您也可以陷入Sigchld(儿童过程死亡)。我不是Windows Guru,因此,如果适用,subprocess不起作用,其他人将不得不在这里鸣叫。

称为App.run()之后,我很好奇过程树的外观。它可能运行exec并接管Python过程空间。如果发生这种情况,创建子过程是我想到的唯一方法。

如果try: App.run() finally: cleanup()不起作用;您可以尝试在子过程中运行它:

import sys
from subprocess import call
rc = call([sys.executable, 'path/to/run_app.py'])
cleanup()

或字符串中的代码,可以使用-c选项,例如:

rc = call([sys.executable, '-c', '''import sys
print(sys.argv)
'''])

您可以通过添加子过程来实现 @tmc的建议 preexec_fn=os.setsid参数(注意:否()),尽管我看不到创建过程组如何在这里有所帮助。或者,您可以尝试shell=True参数以在单独的外壳中运行。

您可能会尝试另一个尝试多处理:

import multiprocessing as mp
if __name__=="__main__":
   p = mp.Process(target=App.run)
   p.start()
   p.join()
   cleanup()

您是否可以将app.run()在try/catch中包装?

类似:

try:
    App.Run()
except (KeyboardInterrupt, SystemExit):
    print "User requested an exit..."
cleanup()

最新更新