在Ctrl-d上,调用Close(),就像文件对象一样

时间:2015-11-27 13:35:41

标签: python multithreading command-line eof

wrote a class继承自 object 并且具有使用某些线程执行任务的子对象实例。有两个socket 侦听器为每个 accept ed连接创建其他线程。他们做他们必须做的事。要完成它们,他们正在查看 Threading.Event 对象以了解它们必须完成。

我注意到,当退出python控制台时,他们没有得到通知(或者没有捕获通知),并且退出不会将控制权返回给bash控制台,除非 Close()之前被调用。

修复它的第一个想法是实现'__ del __'方法,以便在退出时使用垃圾收集器清除它。

class ServiceProvider(object):
    def __init__(self):
        super(ServiceProvider,self).__init__()
        #...
        self.Open()
    def Open(self):
        #... Some threads are created.
    def Close(self):
        #.... Threading.Event to report the threads to finish
    def __del__(self):
        self.Close()

但行为是一样的。如果我在这些方法中放置一个打印件,不在'__ del __'中,在'Close'中都不会写入。除非之前关闭,否则会写入 del 中的打印。

然后我实现了'__ enter __''__ exit __'方法来管理 with 语句。并且 exit 按预期运行,当 with 结束时,事情就会释放。但我真正想要的是像文件描述符这样的事件,如果没有调用 file.close(),它会在退出程序时执行。

class ServiceProvider(object):
    #...
    def __enter__(self):
        return self
    def __exit__(self):
        self.Close()

正在搜索我尝试使用atexit的更多解决方案,但不是。我有类似的结果,不能解决问题。即使我收集了此类创建的所有对象,如果列表中的对象已经关闭 doOnExit 也只会写入其打印。

import atexit
global objects2Close
objects2Close = []

@atexit.register
def doOnExit():
    for obj in objects2Close:
        obj.Close()

class ServiceProvider(object):
    def __init__(self):
        super(ServiceProvider,self).__init__()
        objects2Close.append(self)

2 个答案:

答案 0 :(得分:0)

当您拥有不想泄露的资源(文件,连接以及您关心的任何其他内容)时,使用with通常是个好主意。

在某个地方,就在你的主循环之外你应该有:

with ServiceProvider(some_params) as service_provider:
  rest_of_the_code()

这样做无论你如何退出rest_of_the_code()(kill -9除外),它都会在最后调用service_provider.Close()。这也适用于异常和中断。杀死-9不起作用,因为该进程在操作系统级别被杀死,并且没有机会尝试恢复。

答案 1 :(得分:0)

我已经找到了解决这个问题的方法。此问题中发布的信息与实际问题无关。

这就像守护程序线程一样简单。

该实现使用一些线程来监听远程连接,他们必须在程序退出时完成执行。但是当所有 no daemon 线程完成时,程序结束。

错误地将那些未设置为守护进程的听众和谈话者,这就是执行等待他们的原因。