简体   繁体   English

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

[英]How to kill a process reliably while testing?

I have a couple of different scripts that require opening a MongoDB instance that go something like this: 我有几个不同的脚本需要打开一个类似这样的MongoDB实例:

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

#Do some stuff

mongod.terminate()

And this works great when the code I'm executing works, but while I'm tinkering, errors inevitably arise. 当我正在执行的代码工作时,这很有效,但是当我修补时,错误不可避免地会出现。 Then the Mongod instance remains running, and the next time I attempt to run the script, it detects that and doesn't open a new one. 然后Mongod实例仍在运行,下次我尝试运行该脚本时,它会检测到并且不会打开一个新脚本。

I can terminate the process from the command line, but this is somewhat tedious. 我可以从命令行终止进程,但这有点单调乏味。 Or I can wrap everything in a try loop, but for some of the scripts, I have to do this a bunch, since every function depends on every other one. 或者我可以在try循环中包装所有内容,但对于某些脚本,我必须这样做,因为每个函数都依赖于其他每个函数。 Is there a more elegant way to force close the process even in the event of an error somewhere else in the code? 即使代码中的其他地方出现错误,是否有更优雅的方法强制关闭进程?

EDIT: Did some testing based on tdelaney's comment, it looks like when I run these scripts in Sublime text and en error is generated, the script doesn't actually finish - it hits the error and then waits with the mongod instance open... i think. 编辑:根据tdelaney的评论进行了一些测试,看起来当我在Sublime文本中运行这些脚本并生成错误时,脚本实际上没有完成 - 它遇到错误然后等待mongod实例打开...我认为。 Once I kill the process in the terminal, sublime text tells me "finished in X seconds with exit code1" 一旦我终止了终端中的进程,sublime文本告诉我"finished in X seconds with exit code1"

EDIT2: On Kirby's suggestion, tried: 编辑2:关于柯比的建议,试过:

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()

The error in testing() seems to prevent anything from continuing, so the atexit never registers and the process keeps running. testing()的错误似乎阻止了任何事情的继续,因此atexit永远不会注册并且进程会继续运行。 Am I missing something obvious? 我错过了一些明显的东西吗

If you're running under CPython, you can cheat and take advantage of Python's destructors: 如果你在CPython下运行,你可以欺骗并利用Python的析构函数:

class PopenWrapper(object):
    def __del__(self):
        if self._child_created:
            self.terminate()

This is slightly ucky, though. 不过,这有点丑陋。 My preference would be to atexit : 我的偏好是atexit

import atexit
mongod = Popen(...)
def cleanup():
    for proc in subprocess._active[:]:
        try: proc.terminate()
        except: pass
atexit.register(cleanup)

Still slightly hack-ish, though. 尽管如此,仍然有点黑客攻击。

EDIT: Try this: 编辑:试试这个:

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()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM