Python子流程引用导致fd耗尽
关于这个职位: 我最近遇到了以下代码段:Python子流程引用导致fd耗尽,python,list,reference,subprocess,python-multithreading,Python,List,Reference,Subprocess,Python Multithreading,关于这个职位: 我最近遇到了以下代码段: # custom_process.py import threading import subprocess myList = [] # module-wide list class Foo(threading.Thread): myprocess = None returncode = None def run(self): self.myprocess = subprocess.Popen
# custom_process.py
import threading
import subprocess
myList = [] # module-wide list
class Foo(threading.Thread):
myprocess = None
returncode = None
def run(self):
self.myprocess = subprocess.Popen(...)
global myList
myList.append(self.myprocess)
... # Code skipped for brevity
self.returncode = self.myprocess.returncode
tmp1, tmp2 = self.myprocess.communicate()
... # Code skipped for brevity
del self.myprocess
在连续调用Foo
的run
方法时,此代码将耗尽系统上可用的文件描述符,并引发异常:打开的文件太多
所以我想知道。。。在处理子流程对象时,文件描述符是随着实际操作系统进程关闭,还是在对Python子流程对象的引用计数变为零时关闭
提前感谢。是的,
del
只会删除对对象的引用,它的名称就是这样,您就可以删除了。要从列表中删除该项,需要使用不同的语法
>>> a = 10
>>> l = [a]
>>> del a
>>> a # the name a will be gone now
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined
>>> l # but the list will still contain 10
[10]
>>> del l[0]
>>> l # but now it is gone
[]
>>>
>a=10
>>>l=[a]
>>>德拉
>>>a#a的名字现在就不见了
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
NameError:未定义名称“a”
>>>l#但该列表仍将包含10个
[10]
>>>德尔l[0]
>>>但现在它不见了
[]
>>>
或者,您可以调用
l.remove(a)
是,del
只会删除对对象的引用,它的名称就是这样。要从列表中删除该项,需要使用不同的语法
>>> a = 10
>>> l = [a]
>>> del a
>>> a # the name a will be gone now
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined
>>> l # but the list will still contain 10
[10]
>>> del l[0]
>>> l # but now it is gone
[]
>>>
>a=10
>>>l=[a]
>>>德拉
>>>a#a的名字现在就不见了
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
NameError:未定义名称“a”
>>>l#但该列表仍将包含10个
[10]
>>>德尔l[0]
>>>但现在它不见了
[]
>>>
或者,您可以调用
l.remove(a)
Popen启动一个新的操作系统进程,并返回一个可用于与之交互的python对象
不过,这两个对象仍然是分开的,删除python对象并不一定会影响单独运行的进程,它只是删除了一种与之交互的方便方式
python Popen对象在进程终止后继续运行是完全合理的,反之亦然
不过,行为将取决于Popen的参数,例如,可以将进程配置为即使在整个脚本终止后仍保持运行
如果它是一个一次性的进程,它应该在communicate()
调用后终止,但您应该检查此调用后的返回代码以进行验证(或者使用poll()
检查它是否处于活动状态)
终止也可能需要一些时间,例如,如果每秒调用此函数1000次,则启动它们的速度可能比终止快,从而导致FD耗尽。Popen启动一个新的操作系统进程,并返回一个可用于与之交互的python对象 不过,这两个对象仍然是分开的,删除python对象并不一定会影响单独运行的进程,它只是删除了一种与之交互的方便方式 python Popen对象在进程终止后继续运行是完全合理的,反之亦然 不过,行为将取决于Popen的参数,例如,可以将进程配置为即使在整个脚本终止后仍保持运行 如果它是一个一次性的进程,它应该在
communicate()
调用后终止,但您应该检查此调用后的返回代码以进行验证(或者使用poll()
检查它是否处于活动状态)
终止也可能需要一些时间,例如,如果每秒调用此函数1000次,则启动它们的速度可能比终止快,从而导致FD耗尽。在保留进程列表的同时,避免FD耗尽的最佳方法是使用进程池。通过这种方式,您可以限制同时打开的进程数,新进程仅在前一个进程结束时启动
当然,关于引用删除和内存耗尽的原因,其他两个答案都是正确的,这也是我不在这里重复的原因。在保留进程列表的同时,避免fd耗尽的最佳方法是使用进程池。通过这种方式,您可以限制同时打开的进程数,新进程仅在前一个进程结束时启动 当然,关于引用删除和内存耗尽的原因,其他两个答案都是正确的,这也是我不在这里重复的原因。如果退出run()方法时不需要,可以使用myprocess.kill()或myprocess.terminate()关闭正在运行的进程。(您的代码片段暗示您不需要) 如果您也不将其添加为属性,也不将其添加到myList(根据您的代码,它是多余的),它将在退出run()后很快被销毁-在Python中,您通常使用垃圾收集器,实际使用del运算符的情况很少您可以使用myprocess.kill()或myprocess.terminate()关闭正在运行的进程-如果退出run()方法时不需要它。(您的代码片段暗示您不需要)
如果您也不将其添加为属性,也不将其添加到myList中(根据您的代码,它是多余的),它将在退出run()后很快被销毁-在Python中,您通常依赖垃圾收集器,实际使用del运算符的情况很少我发现了一篇非常好的博客文章,准确地描述了我所面临的情况:
通过强调*nixes和Windows在文件处理方面的差异,直观地解决了这个问题。作者甚至提出了一个解决方案!绝对值得一读。我发现了一篇非常好的博客文章,准确地描述了我所面临的情况:
通过强调*nixes和Windows在文件处理方面的差异,直观地解决了这个问题。作者甚至提出了一个解决方案!绝对值得一读。为什么要将其存储在
我的列表中?@thefourtheye没有任何目的。我现在知道我不应该。然而sto