Python:在记录内存时获取子进程 STDOUT

Posted

技术标签:

【中文标题】Python:在记录内存时获取子进程 STDOUT【英文标题】:Python : Get subprocess STDOUT while logging the memory 【发布时间】:2017-09-10 03:56:11 【问题描述】:

这是我的问题:

我正在尝试编写代码来记录子进程作业占用的内存并同时获取该作业的标准输出。

为此,我使用 subprocess 调用 python 脚本:

res = Popen(args, shell=False, stderr=STDOUT, stdout=PIPE)

为了获取内存,我使用 res.pid 获取作业的 pid。 然后我用 psutil 获取内存:

p = psutil.Process(pid)

mem_usage = p.memory_full_info()

我想按以下方式组合:

运行代码

每秒,将内存记录在 mem_usage 中

将标准错误记录在字符串列表中

我试过了:

while res.poll() is None:

    (total_rss_Mo, total_vms_Mo, total_uss_Mo) = get_mem(pid)
    print "MEM ",total_rss_Mo, total_vms_Mo, total_uss_Mo

    # Wait a bit before next memory scam
    time.sleep(1)
stderr, stdout = res.communicate()

结果不是我所期望的。前 20 年代,它可以工作,但随后工作进入休眠状态,永无止境:

MEM  7.77734375 152.52734375 4.30078125
MEM  290.49609375 1299.66015625 284.265625
MEM  436.53515625 1372.29296875 427.77734375
MEM  443.61328125 1633.8125 434.921875
MEM  544.26171875 1732.52734375 535.40625
MEM  548.59765625 1737.015625 539.89453125
MEM  552.765625 1741.01953125 543.8984375
MEM  552.51953125 1741.01953125 543.8984375
MEM  552.5703125 1741.01953125 543.8984375
MEM  552.55078125 1741.01953125 543.8984375
MEM  552.7265625 1741.01953125 543.8984375
MEM  455.63671875 1643.8828125 446.76171875
MEM  455.63671875 1643.8828125 446.76171875
MEM  455.63671875 1643.8828125 446.76171875
MEM  455.63671875 1643.8828125 446.76171875
MEM  455.63671875 1643.8828125 446.76171875

似乎 stderr 缓冲区已满并暂停作业。 如何获取 stderr/stdout 并同时记录我的内存? 如果我尝试在循环中读取标准输出,则循环将持续到作业结束,并且我无法再在作业执行期间记录内存:

while True:
    line = res.stdout.readline()
    if not line or line == "":
        break
    print line

感谢您的帮助,

阿基拉

【问题讨论】:

为什么不把输出读取循环放在内存循环里面呢?即在每次迭代中,读取输出直到出现空行,然后检查内存。 当 stderr 缓冲区已满时,您正在运行什么作业会卡住? 致 lolopop :这份工作是太空望远镜的图像模拟器。它吐出大量描述它正在做什么的行。致 FamousJameous:无论我把输出读取循环放在哪里,它都会一直读取并且在工作完成之前永远不会退出循环。所以我没有得到任何内存日志。 \n 我想要做的是只读取到该点已经生成的输出行,然后退出循环。然后我可以记录内存并在之后继续检查输出。 【参考方案1】:

我通过将内存记录放在单独的线程中找到了解决方案。它不再与获取子进程的 stdout/stderr 的循环发生冲突。

【讨论】:

以上是关于Python:在记录内存时获取子进程 STDOUT的主要内容,如果未能解决你的问题,请参考以下文章

发生异常时,Python Pandoc子进程不打印STDOUT

使用 Python 子进程通信方法时如何获取退出代码?

如何异步获取子进程'stdout数据?

没有STDOUT的两个python脚本之间的进程间通信

如何在python中杀死一个分叉的孩子及其jackd子进程

Python asyncio子进程连续写入stdin和读取stdout/stderr