如何使用标准 Linux 工具修复死锁脚本?

How to use standard Linux tools to fix a deadlocked script?

我在 Python3 中有一个脚本,如果我使用 subprocess.Popen.wait() 我有问题 — 我的脚本多次重复一些 Linux 命令,在我看来我的应用程序不是响应。当我使用 subprocess.Popen.communicate() 时,我的应用程序在一秒钟内正确地完成了它的工作。 使用Linux解决这个问题的正确方法是什么?

我想解决办法一定是在操作buffer变量的地方,但是我翻遍了整个互联网,没有找到合适的。可能是我对 Linux 的整体结构和操作了解不够。

我的问题可以重新表述如下:当我使用 .wait() 方法时到底发生了什么?那会导致失败吗?等待这么久的原因是什么? 当我中止 运行ning 任务时,我看到下一条日志:

Traceback (most recent call last):
  File "./test.py", line 6, in <module>
    proc.wait()
  File "/usr/lib/python3.5/subprocess.py", line 1658, in wait
    (pid, sts) = self._try_wait(0)
  File "/usr/lib/python3.5/subprocess.py", line 1608, in _try_wait
    (pid, sts) = os.waitpid(self.pid, wait_flags)
KeyboardInterrupt

我的文件看起来大致如下: script.py:

#!/usr/bin/python3
# -*-coding: utf-8 -*-

import subprocess
proc = subprocess.Popen(['./1.py', '1000000'], stdin=subprocess.PIPE, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
proc.wait()
out = proc.stdout.read()
# out = proc.communicate()[0]
print(len(out))

1.py:

#!/usr/bin/python3
# -*-coding: utf-8 -*-

import sys

x = sys.argv[-1]

# print(x, type(x))
for i in range(int(x)):
  print(i)

更新:据我们了解,问题是缓冲区溢出。最后一个版本的问题是,如何在 运行 脚本之前使用 Linux 扩展缓冲区或将缓冲区重定向到文件的可能性?

UPD2:我还尝试了 运行 脚本:$ python3 -u ./script.py,但不幸的是,没有缓冲无法正常工作,脚本挂起。

您的脚本正在将输出发送到其 stdoutstderr 管道。操作系统将缓冲一些数据,然后在管道填满时永远阻塞进程。假设我有一个长篇大论的命令,比如

longwinded.py:

for i in range(100000):
    print('a'*1000)

以下挂起,因为标准输出管道已满

import sys
import subprocess as subp
p = subp.Popen([sys.executable, 'longwinded.py'], stdout=subp.PIPE,
    stderr=subp.PIPE)
p.wait()

下一个不会挂起,因为 communicate 将 stdout 和 stderr 管道读入内存

p = subp.Popen([sys.executable, 'longwinded.py'], stdout=subp.PIPE,
    stderr=subp.PIPE)
p.communicate()

如果你不关心stdout和err是什么,你可以将它们重定向到空设备

p = subp.Popen([sys.executable, 'longwinded.py'], 
    stdout=open(os.devnull, 'w'), 
    stderr=open(os.devnull, 'w'))
p.wait()

或将它们保存到文件

p = subp.Popen([sys.executable, 'longwinded.py'], 
    stdout=open('mystdout', 'w'), 
    stderr=open('mystderr', 'w'))
p.wait()