Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/batch-file/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python';s主线程停止时是否收集垃圾?_Python_Python 2.6_Python Multithreading - Fatal编程技术网

Python';s主线程停止时是否收集垃圾?

Python';s主线程停止时是否收集垃圾?,python,python-2.6,python-multithreading,Python,Python 2.6,Python Multithreading,在多线程Python进程中,我有许多非守护进程线程,我指的是即使在主线程退出/停止后仍保持主进程活动的线程 我的非守护进程线程保留主线程中的某些对象,但当主线程结束时(控件从文件底部脱落),这些对象似乎不会被垃圾收集,我的弱引用终结器回调也不会触发 我期望主线程被垃圾收集是错误的吗?我本以为线程局部数会被释放(即垃圾回收) 我错过了什么 支持材料 pprint.pprint(threading.enumerate())的输出,显示主线程在其他线程打开时已停止 [<_MainThread(

在多线程Python进程中,我有许多非守护进程线程,我指的是即使在主线程退出/停止后仍保持主进程活动的线程

我的非守护进程线程保留主线程中的某些对象,但当主线程结束时(控件从文件底部脱落),这些对象似乎不会被垃圾收集,我的弱引用终结器回调也不会触发

我期望主线程被垃圾收集是错误的吗?我本以为线程局部数会被释放(即垃圾回收)

我错过了什么


支持材料

pprint.pprint(threading.enumerate())
的输出,显示主线程在其他线程打开时已停止

[<_MainThread(MainThread, stopped 139664516818688)>,
 <LDQServer(testLogIOWorkerThread, started 139664479889152)>,
 <_Timer(Thread-18, started 139663928870656)>,
 <LDQServer(debugLogIOWorkerThread, started 139664437925632)>,
 <_Timer(Thread-17, started 139664463103744)>,
 <_Timer(Thread-19, started 139663937263360)>,
 <LDQServer(testLogIOWorkerThread, started 139664471496448)>,
 <LDQServer(debugLogIOWorkerThread, started 139664446318336)>]
[,,
,
,
,
,
,
,
]
由于有人总是询问用例

我的网络服务偶尔会错过实时截止日期(在最坏的情况下,这会导致整个系统故障)。这原来是因为每当文件系统发脾气时,(重要的)调试数据的日志记录都会被阻塞。因此,我试图改造一些已建立的专门日志库,将阻塞I/O延迟到工作线程

不幸的是,已建立的使用模式是记录重叠并行事务的短期日志通道和从不显式关闭的长期模块作用域通道的混合

所以我创建了一个decorator,它将方法调用延迟到工作线程。工作线程是非守护进程,以确保所有(慢速)阻塞I/O在解释器退出之前完成,并保留对客户端的弱引用(方法调用进入队列)。当客户端被垃圾收集时,弱引用的回调将触发,工作线程知道不再有工作排队,因此将在下次方便时退出


这似乎在除了一个重要用例之外的所有用例中都能正常工作:当日志通道位于主线程中时。当主线程停止/退出时,日志记录通道未完成,因此我的(非守护进程)工作线程将继续保持整个进程的活动状态。

主线程结束时不调用所有非守护进程线程上的
join
,或者对不调用时发生的情况做出任何假设,这是一个坏主意


如果您没有做任何非常不寻常的事情,CPython(至少-)将自动在所有非守护进程线程上调用
join
,作为
\u主线程对。\u exitfunc
。这实际上并没有文档记录,所以你不应该依赖它,但它是发生在你身上的事情

你的主线程实际上根本没有退出;它在它的
\u主线程中阻塞。\u exitfunc
试图
加入一些任意的非守护进程线程。在调用
atexit
处理程序之前,它的对象不会被最终确定,而这在它完成加入所有非守护进程线程之后才会发生


同时,如果您避免了这种情况(例如,直接使用
线程
/
\u线程
,或者将主线程与其对象分离,或者强制其进入正常的
线程
实例),会发生什么?它没有定义。
threading
模块根本没有引用它,但是在CPython 2.0-3.3中,很可能在任何其他合理的实现中,它由用户决定。正如文件所说:

当主线程退出时,由系统定义其他线程是否存活。在使用本机线程实现的SGI IRIX上,它们仍然存在。在大多数其他系统上,它们在不执行try的情况下被杀死。。。最后是子句或正在执行的对象析构函数

因此,如果您设法避免
join
ing您的所有非守护进程线程,那么您必须编写代码,既能像守护进程线程一样硬杀死它们,又能让它们继续运行直到退出

如果它们继续运行,至少在POSIX系统上的CPython 2.7和3.3中是这样,那么主线程的OS级线程句柄和表示它的各种更高级别Python对象可能仍然会被保留,并且不会被GC清除


最重要的是,即使所有东西都发布了,你也不能依赖GC删除任何东西。如果您的代码依赖于确定性GC,那么在CPython中有许多情况可以避免(尽管您的代码随后会在PyPy、Jython、IronPython等中中断),但退出时不是其中之一。CPython可以,也将在退出时泄漏对象,并让操作系统对其进行分类。(这就是为什么从不关闭的可写文件可能会丢失最后几次写入,
\uu del\uu
方法永远不会被调用,因此没有人告诉它们进行
刷新
,至少在POSIX上,底层的
文件*
也不会自动刷新。)

如果您希望在主线程结束时清理某些内容,则必须使用某种
关闭
函数,而不是依赖于
\uuu del_uu
,并且必须确保它通过主代码块周围的
块、
atexit
函数或其他机制触发


最后一件事:

我本以为线程局部数会被释放(即垃圾回收)


你在什么地方真的有线程吗?或者你只是指只能在一个线程中访问的局部变量和/或全局变量吗?

有很多假设需要在没有具体代码示例的情况下回答这个问题。。。也就是说,您是否尝试过显式地关闭/删除主线程末尾的日志通道,只是为了查看弱引用的回调是否会被触发?我指的是仅在一个线程中访问的局部变量和/或全局变量。我将尝试使用线程的本地属性,看看它能做什么。我从来没有听说过ab