2

我正在开发一个通过 Bottle 框架由网页控制的小型 python 应用程序。问题是我有时会在后台运行线程,但是如果 Bottle 实例被关闭,例如通过 Ctrl+C,它就会挂起,因为这些线程从未被告知退出。有没有办法捕捉 Bottle 服务器关闭并调用方法进行一些清理?

4

4 回答 4

2

try/ finally:

# start threads here

try:
    bottle.run(...)  # or app.run(...)

finally:
    # clean up (join) threads here

编辑:感谢@linusg 正确指出 try 块甚至不需要。最好只使用:

# start threads here

bottle.run(...)  # or app.run(...)

# if we reach here, run has exited (Ctrl-C)

# clean up (join) threads here
于 2013-10-15T15:38:41.633 回答
0

__del__.

就像是:

class MyApp(bottle.Bottle):
    def __del__(self):
        # clean up threads here

# from here it's just business as usual
app = MyApp()

@app.route('/')
def home()
    return 'hello, world.\n'

app.run('127.0.0.1', 8080)
于 2013-10-15T13:28:21.420 回答
0

如果您的线程不需要优雅地关闭,那么只需让它们成为守护线程,您的进程将干净地退出而无需进一步更改。

可以将线程标记为“守护线程”。这个标志的意义在于,当只剩下守护线程时,整个 Python 程序就退出了。初始值继承自创建线程。可以通过 daemon 属性设置标志。

t = threading.Thread(target=myfunc)
t.daemon = True
t.start()

# because t is a daemon thread, no need to join it at process exit.

注意,您问题的措辞暗示您真正的问题是它们导致您的进程在退出时挂起,而不是他们需要释放资源,但值得指出的是:

注意:守护线程在关闭时突然停止。它们的资源(如打开的文件、数据库事务等)可能无法正常释放。

于 2013-10-15T15:44:32.577 回答
0

听起来你想要一个上下文管理器:

from contextlib import contextmanager
#Code for server goes here

@contextmanager
def server_with_threads():
    try:
        spawn_thread_things()
        yield MyServer()
    finally:
        close_thready_things()

#Or maybe here

with server_with_threads() as server:
    server.run('127.0.0.1', 8080)

一旦您的服务器正常关闭或抛出异常(基本上退出 with 块),它将达到finally条件并清理您的线程。

另一种选择是atexit

于 2013-10-15T13:40:45.517 回答