Python 如何在测试时可靠地终止进程?
我有两个不同的脚本需要打开MongoDB实例,如下所示:Python 如何在测试时可靠地终止进程?,python,mongodb,Python,Mongodb,我有两个不同的脚本需要打开MongoDB实例,如下所示: mongod = Popen( ["mongod", "--dbpath", '/path/to/db'], ) #Do some stuff mongod.terminate() 当我正在执行的代码工作时,这非常有效,但是当我在修补时,不可避免地会出现错误。然后Mongod实例仍在运行,下次我尝试运行脚本时,它会检测到这一点,并且不会打开新实例 我可以从命令行终止进程,但这有点乏味。或者,我可以将所有内容包
mongod = Popen(
["mongod", "--dbpath", '/path/to/db'],
)
#Do some stuff
mongod.terminate()
当我正在执行的代码工作时,这非常有效,但是当我在修补时,不可避免地会出现错误。然后Mongod实例仍在运行,下次我尝试运行脚本时,它会检测到这一点,并且不会打开新实例
我可以从命令行终止进程,但这有点乏味。或者,我可以将所有内容包装在try
循环中,但对于某些脚本,我必须执行大量操作,因为每个函数都依赖于其他函数。是否有一种更优雅的方法,即使在代码中的其他地方发生错误时,也可以强制关闭进程
编辑:根据tdelaney的评论做了一些测试,看起来当我在Sublime文本中运行这些脚本并生成en错误时,脚本实际上并没有完成-它遇到错误,然后等待mongod实例打开。。。我想。一旦我在终端中终止进程,升华文本告诉我“退出代码1,在X秒内完成”
编辑2:根据Kirby的建议,尝试:
def testing():
mongod = Popen(
["mongod", "--dbpath", '/Users/KBLaptop/computation/db/'],
)
#Stuff that generates error
mongod.terminate()
def cleanup():
for proc in subprocess._active[:]:
try: proc.terminate()
except: pass
atexit.register(cleanup)
testing()
testing()
中的错误似乎阻止了任何事情的继续,因此atexit
从未注册,并且进程一直在运行。我是否遗漏了一些明显的东西?如果您在CPython下运行,您可以作弊并利用Python的析构函数:
class PopenWrapper(object):
def __del__(self):
if self._child_created:
self.terminate()
不过,这有点不吉利。我倾向于atexit
:
import atexit
mongod = Popen(...)
def cleanup():
for proc in subprocess._active[:]:
try: proc.terminate()
except: pass
atexit.register(cleanup)
不过还是有点像黑客
编辑:尝试以下操作:
from subprocess import Popen
import atexit
started = []
def auto_popen(*args, **kw):
p = Popen(*args, **kw)
started.append(p)
return p
def testing():
mongod = auto_popen(['blah blah'], shell=True)
assert 0
#Stuff that generates error
mongod.terminate()
def cleanup():
for proc in started:
if proc.poll() is None:
try: proc.kill()
except: pass
atexit.register(cleanup)
testing()
您可以维护活动进程的全局列表,并注册杀死它们的
atexit
处理程序。你甚至可以用一个新的Popen
来修改子进程
。@tdelaney你愿意详细说明一下吗?我还是个新手。查看了atexit
的文档,看起来这将是正确的调用,但并不真正理解如何实现它。我尝试将上述代码放入函数中并调用atexit.register(func())
,也只是将atexit.register(mongod)
放在脚本末尾,或者atexit.register(mongod.terminate())
。。。很明显,我不明白它在做什么。@t事实上,也许退欧不是最好的方式。。。请参阅第二位代码中的“我的编辑”(简短版本:脚本似乎会吐出错误,但在我在终端中杀死它之前不会真正退出),atexit在哪里?刚刚尝试了第二部分-我遇到了与上面编辑中相同的问题。也就是说,这个过程永远不会结束。无论是在原始函数之后调用cleanup()
,还是执行atexit.register(cleanup())
,代码都不会到达cleanup函数,因此进程保持打开状态。我没有在CPython下运行,至少据我所知不是这样。@kevbonham您应该在不调用函数的情况下传递函数。另外,如果您的Python没有说IronPython、PyPy或Jython,那么您使用的是CPython。它没有明确地说CPython。啊,明白了-谢谢你的解释。不幸的是,这似乎无法解决问题,请参见我的编辑2。@kevbonham Ack,我想我将if语句写反了。如果proc.poll()为None,请尝试。