我正在使用使用Python作为其脚本API的一部分的商业应用程序。提供的功能之一就是称为App.run()
。当调用此功能时,它将启动一个新的Java进程,该进程完成其余的执行。(不幸的是,由于提供的Python模块是.pyc
文件,我真的不知道它在引擎盖下做什么,而且许多Python函数都是SWIG生成的)。
我遇到的问题是,我正在将App.run()
调用构建到一个较大的Python应用程序中,该应用程序需要执行一些保证的清理代码(关闭数据库等)。不幸的是,如果子过程被 ctrl c 中断,则它中断并返回命令行而无需返回控件到主Python程序。因此,我的清理代码永远不会执行。
到目前为止,我已经尝试过:
- 在Atexit上注册功能...不起作用
- 将清理放入
__del__
destructor类中...不起作用。(App.run()
在同类中) - 为 ctrl c 创建一个信号处理程序。
- 将
App.run()
放入线程中... ctrl c
后导致内存故障 - 将
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()