【问题标题】:Memory usage when reading lines from a piped subprocess stdout in python从 python 中的管道子进程 stdout 读取行时的内存使用情况
【发布时间】:2016-05-19 22:45:27
【问题描述】:

我只是想了解在处理 subprocess.Popen() 结果并逐行读取时在内存使用方面在“背景”中发生了什么。这是一个简单的例子。

给定以下脚本test.py 打印“Hello”然后等待 10 秒并打印“world”:

import sys
import time
print ("Hello")
sys.stdout.flush()
time.sleep(10)
print ("World")

然后下面的脚本test_sub.py 将调用作为子进程'test.py',将标准输出重定向到管道,然后逐行读取:

import subprocess, time, os, sy

cmd = ["python3","test.py"]

p = subprocess.Popen(cmd,
                     stdout=subprocess.PIPE,
                     stderr=subprocess.STDOUT, universal_newlines = True)

for line in iter(p.stdout.readline, ''):
   print("---" + line.rstrip())

在这种情况下,我的问题是,当我在执行子进程调用后运行 test_sub.py 时,它会打印“Hello”,然后等待 10 秒,直到“world”出现然后打印它,会发生什么“你好”在这 10 秒的等待中?它会在test_sub.py 完成之前存储在内存中,还是在第一次迭代中被丢弃?

这对于这个例子来说可能无关紧要,但在处理非常大的文件时它确实如此。

【问题讨论】:

    标签: python memory subprocess popen ram


    【解决方案1】:

    在这 10 秒的等待中,“Hello”会发生什么?

    "Hello"(在父级中)可通过line 名称获得,直到.readline() 第二次返回,即"Hello" 至少在@987654327 的输出之前存在 @ 在父级中读取。

    如果您的意思是在子进程中发生的事情,那么在 sys.stdout.flush() 之后,"Hello" 对象没有理由继续存在,但它可能例如参见 Does Python intern strings?

    它是在 test_sub.py 完成之前存储在内存中,还是在第一次迭代中被丢弃?

    .readline()第二次返回后,line引用"World""Hello" 之后会发生什么取决于特定 Python 实现中的垃圾收集,即,即使 line"World";对象"Hello" 可能会继续存在一段时间。 Releasing memory in Python.

    您可以设置 PYTHONDUMPREFS=1 envvar 并使用 debug python 构建运行您的代码,以查看在 python 进程退出时仍处于活动状态的对象。例如,考虑以下代码:

    #!/usr/bin/env python3
    import threading
    import time
    import sys
    
    def strings():
        yield "hello"
        time.sleep(.5)
        yield "world"
        time.sleep(.5)
    
    def print_line():
        while True:
            time.sleep(.1)
            print('+++', line, file=sys.stderr)
    
    threading.Thread(target=print_line, daemon=True).start()
    for line in strings():
        print('---', line)
    time.sleep(1)
    

    它表明line 直到第二个yield 才反弹。 PYTHONDUMPREFS=1 ./python . |& grep "'hello'" 的输出 表明当python 退出时'hello' 仍然存在。

    【讨论】:

      猜你喜欢
      • 2012-11-16
      • 2011-11-12
      • 2017-09-10
      • 2010-10-19
      • 2013-02-17
      • 2021-03-30
      • 1970-01-01
      • 1970-01-01
      • 2021-10-13
      相关资源
      最近更新 更多