停止读取Python中没有挂起的进程输出?
我有一个针对Linux的Python程序,看起来几乎像这样:停止读取Python中没有挂起的进程输出?,python,subprocess,multiprocessor,hung,Python,Subprocess,Multiprocessor,Hung,我有一个针对Linux的Python程序,看起来几乎像这样: import os import time process = os.popen("top").readlines() time.sleep(1) os.popen("killall top") print process 程序挂起在这一行: process = os.popen("top").readlines() 这种情况发生在那些像“Top”一样保持更新输出的工具中 我的最佳尝试: import os import
import os
import time
process = os.popen("top").readlines()
time.sleep(1)
os.popen("killall top")
print process
程序挂起在这一行:
process = os.popen("top").readlines()
这种情况发生在那些像“Top”一样保持更新输出的工具中
我的最佳尝试:
import os
import time
import subprocess
process = subprocess.Popen('top')
time.sleep(2)
os.popen("killall top")
print process
它比第一个(kelled)更有效,但它的回报是:
<subprocess.Popen object at 0x97a50cc>
和第一个一样。由于“readlines()”而挂起
它的返回应该是这样的:
top - 05:31:15 up 12:12, 5 users, load average: 0.25, 0.14, 0.11
Tasks: 174 total, 2 running, 172 sleeping, 0 stopped, 0 zombie
Cpu(s): 9.3%us, 3.8%sy, 0.1%ni, 85.9%id, 0.9%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 1992828k total, 1849456k used, 143372k free, 233048k buffers
Swap: 4602876k total, 0k used, 4602876k free, 1122780k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
31735 Barakat 20 0 246m 52m 20m S 19.4 2.7 13:54.91 totem
1907 root 20 0 91264 45m 15m S 1.9 2.3 38:54.14 Xorg
2138 Barakat 20 0 17356 5368 4284 S 1.9 0.3 3:00.15 at-spi-registry
2164 Barakat 9 -11 164m 7372 6252 S 1.9 0.4 2:54.58 pulseaudio
2394 Barakat 20 0 27212 9792 8256 S 1.9 0.5 6:01.48 multiload-apple
6498 Barakat 20 0 56364 30m 18m S 1.9 1.6 0:03.38 pyshell
1 root 20 0 2880 1416 1208 S 0.0 0.1 0:02.02 init
2 root 20 0 0 0 0 S 0.0 0.0 0:00.02 kthreadd
3 root RT 0 0 0 0 S 0.0 0.0 0:00.12 migration/0
4 root 20 0 0 0 0 S 0.0 0.0 0:02.07 ksoftirqd/0
5 root RT 0 0 0 0 S 0.0 0.0 0:00.00 watchdog/0
9 root 20 0 0 0 0 S 0.0 0.0 0:01.43 events/0
11 root 20 0 0 0 0 S 0.0 0.0 0:00.00 cpuset
12 root 20 0 0 0 0 S 0.0 0.0 0:00.02 khelper
13 root 20 0 0 0 0 S 0.0 0.0 0:00.00 netns
14 root 20 0 0 0 0 S 0.0 0.0 0:00.00 async/mgr
15 root 20 0 0 0 0 S 0.0 0.0 0:00.00 pm
并保存在变量“process”中。伙计们,我现在真的被卡住了吗?我建议用“ps”代替“top”,它会给你同样的信息,但只能一次,而不是永远一秒钟一次
您还需要在ps中使用一些标志,我倾向于使用“ps aux”而不是这种方法,我要做的是检查您试图从中获取信息的程序,并确定该信息的最终来源。它可能是API调用或设备节点。然后,编写一些python,从同一个源代码获取它。这消除了“抓取”已处理数据的问题和开销 仅打印输出部分的尾部解决方案 您可以在另一个线程中读取进程输出,并保存队列中最后一行的所需数量:
import collections
import subprocess
import time
import threading
def read_output(process, append):
for line in iter(process.stdout.readline, ""):
append(line)
def main():
# start process, redirect stdout
process = subprocess.Popen(["top"], stdout=subprocess.PIPE, close_fds=True)
try:
# save last `number_of_lines` lines of the process output
number_of_lines = 200
q = collections.deque(maxlen=number_of_lines) # atomic .append()
t = threading.Thread(target=read_output, args=(process, q.append))
t.daemon = True
t.start()
#
time.sleep(2)
finally:
process.terminate() #NOTE: it doesn't ensure the process termination
# print saved lines
print ''.join(q)
if __name__=="__main__":
main()
此变体要求q.append()
是原子操作。否则,输出可能已损坏
解决方案
您可以使用在指定的超时后调用进程。terminate()
,而不是在另一个线程中读取。尽管它可能与子流程
模块的交互不太好。基于:
此方法仅适用于*nix系统。如果process.stdout.readline()
没有返回,它可能会阻塞
解决方案
这种方法也适用于Windows。这里我使用了process.stdout
作为一个iterable;它可能会引入额外的输出缓冲,如果不需要,您可以切换到iter(process.stdout.readline,”)
方法。如果进程没有在process.terminate()
上终止,则脚本将挂起
没有线程,就没有信号解决方案
导入集合
导入子流程
导入系统
导入时间
def main():
args=sys.argv[1:]
如果不是args:
args=['top']
#启动进程,重定向标准输出
process=subprocess.Popen(args,stdout=subprocess.PIPE,close_fds=True)
#保存流程输出的最后“行数”
_线的数量=200
q=collections.deque(maxlen=行数)
超时=2秒
现在=开始=时间。时间()
while(现在-启动)<超时:
line=process.stdout.readline()
如果不是直线:
打破
q、 追加(行)
now=time.time()
否则:#超时
process.terminate()
#打印保存的行
打印“”连接(q),
如果名称=“\uuuuu main\uuuuuuuu”:
main()
这种变体既不使用线程,也不使用信号,但会在终端中产生乱码输出。如果process.stdout.readline()
阻塞,它将被阻塞。(J.F.Sebastian您的代码工作得很好,我认为它比我的解决方案好=)
我用另一种方法解决了它
我没有直接在终端上生成输出,而是将其生成一个文件“tmp_file”:
然后我使用工具“cut”将其输出“这是最高输出”作为流程的值
cat tmp_file
它做了我想要它做的。这是最后的代码:
import os
import subprocess
import time
subprocess.Popen("top >> tmp_file",shell = True)
time.sleep(1)
os.popen("killall top")
process = os.popen("cat tmp_file").read()
os.popen("rm tmp_file")
print process
# Thing better than nothing =)
非常感谢大家在事实方面提供的帮助,如果你填满了输出缓冲区,你会得到一些答案。因此,一种解决方案是用一个大的垃圾输出(大约6000个字符,bufsize=1)填充缓冲区 比方说,您有一个在sys.stdout上编写的python脚本,而不是top:
GARBAGE='.\n'
sys.stdout.write(valuable_output)
sys.stdout.write(GARBAGE*3000)
在启动器端,而不是简单的进程。readline()
它确实有点脏,因为2000依赖于子流程的实现,但它工作得很好,而且非常简单。设置bufsize=1以外的任何值都会使事情变得更糟。
子流程。Popen
对象没有属性读取行
。top就是这种程序的完美示例。。。你没用陀螺吗?你在用什么程序?airodump ng这是Aircrack ng tools中的一个工具,它的输出像Top。非常感谢,这太棒了。上面的代码有许多问题,例如,os.popen()
不应像代码2中那样使用。我已经更新了我的答案,包括一个打印所有程序输出的变体(不仅仅是从末尾开始的指定行数)
import collections
import subprocess
import threading
def main():
# start process, redirect stdout
process = subprocess.Popen(["top"], stdout=subprocess.PIPE, close_fds=True)
# terminate process in timeout seconds
timeout = 2 # seconds
timer = threading.Timer(timeout, process.terminate)
timer.start()
# save last `number_of_lines` lines of the process output
number_of_lines = 200
q = collections.deque(process.stdout, maxlen=number_of_lines)
timer.cancel()
# print saved lines
print ''.join(q),
if __name__=="__main__":
main()
import collections
import subprocess
import sys
import time
def main():
args = sys.argv[1:]
if not args:
args = ['top']
# start process, redirect stdout
process = subprocess.Popen(args, stdout=subprocess.PIPE, close_fds=True)
# save last `number_of_lines` lines of the process output
number_of_lines = 200
q = collections.deque(maxlen=number_of_lines)
timeout = 2 # seconds
now = start = time.time()
while (now - start) < timeout:
line = process.stdout.readline()
if not line:
break
q.append(line)
now = time.time()
else: # on timeout
process.terminate()
# print saved lines
print ''.join(q),
if __name__=="__main__":
main()
top >> tmp_file
cat tmp_file
import os
import subprocess
import time
subprocess.Popen("top >> tmp_file",shell = True)
time.sleep(1)
os.popen("killall top")
process = os.popen("cat tmp_file").read()
os.popen("rm tmp_file")
print process
# Thing better than nothing =)
GARBAGE='.\n'
sys.stdout.write(valuable_output)
sys.stdout.write(GARBAGE*3000)
GARBAGE='.\n'
line=process.readline()
while line==GARBAGE:
line=process.readline()