如何在测试时可靠地杀死进程?

时间:2015-04-15 16:18:11

标签: python mongodb

我有几个不同的脚本需要打开一个类似这样的MongoDB实例:

mongod = Popen(
        ["mongod", "--dbpath", '/path/to/db'],
    )

#Do some stuff

mongod.terminate()

当我执行的代码工作时,这很有效,但是当我修补时,错误不可避免地会出现。然后Mongod实例仍在运行,下次我尝试运行该脚本时,它会检测到并且不会打开一个新脚本。

我可以从命令行终止进程,但这有点单调乏味。或者我可以在try循环中包装所有内容,但是对于某些脚本,我必须这样做,因为每个函数都依赖于其他每个函数。即使在代码中的其他地方发生错误,是否有更优雅的方法强制关闭进程?

编辑:根据tdelaney的评论进行了一些测试,看起来当我在Sublime文本中运行这些脚本并生成错误时,脚本实际上没有完成 - 它会遇到错误,然后等待mongod实例打开......我想。一旦我终止了终端中的进程,sublime文本告诉我"finished in X seconds with exit code1"

EDIT2:关于柯比的建议,尝试过:

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永远不会注册,并且进程会继续运行。我错过了一些明显的东西吗?

1 个答案:

答案 0 :(得分:3)

如果你在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()