停止读取Python中的进程输出而不挂起?

停止读取Python中的进程输出而不挂起?

我有一个用于Linux的Python程序,与此类似:

import osimport time

process = os.popen("top").readlines()time.sleep(1)os.popen("killall top")print process

程序挂在下面一行:

process = os.popen("top").readlines()

这种情况发生在那些不断更新输出的工具中,比如“top”

我最好的审判:

import osimport timeimport subprocess

process = subprocess.Popen('top')time.sleep(2)os.popen("killall top")print process

它比第一个更好地工作(它已经被封住了),但是它返回:

<subprocess.Popen object at 0x97a50cc>

第二次审判:

import osimport timeimport subprocess

process = subprocess.Popen('top').readlines()time.sleep(2)os.popen("killall top")print process

和第一个一样。由于“readline()”,它挂了。

它的返回应该是这样的:

  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

并保存在变量“Process”中。我有什么想法吗,伙计们,我现在真的被困住了?


临摹微笑
浏览 457回答 3
3回答

MMMHUHU

#!/usr/bin/env&nbsp;python"""Start&nbsp;process;&nbsp;wait&nbsp;2&nbsp;seconds;&nbsp;kill&nbsp;the&nbsp;process;&nbsp;print&nbsp;all&nbsp;process&nbsp;output."" "import&nbsp;subprocessimport&nbsp;tempfileimport&nbsp;timedef&nbsp;main(): &nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;open&nbsp;temporary&nbsp;file&nbsp;(it&nbsp;automatically&nbsp;deleted&nbsp;when&nbsp;it&nbsp;is&nbsp;closed) &nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;&nbsp;`Popen`&nbsp;requires&nbsp;`f.fileno()`&nbsp;so&nbsp;`SpooledTemporaryFile`&nbsp;adds&nbsp;nothing&nbsp;here &nbsp;&nbsp;&nbsp;&nbsp;f&nbsp;=&nbsp;tempfile.TemporaryFile()&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;start&nbsp;process,&nbsp;redirect&nbsp;stdout &nbsp;&nbsp;&nbsp;&nbsp;p&nbsp;=&nbsp;subprocess.Popen(["top"],&nbsp;stdout=f) &nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;wait&nbsp;2&nbsp;seconds &nbsp;&nbsp;&nbsp;&nbsp;time.sleep(2) &nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;kill&nbsp;process &nbsp;&nbsp;&nbsp;&nbsp;#NOTE:&nbsp;if&nbsp;it&nbsp;doesn't&nbsp;kill&nbsp;the&nbsp;process&nbsp;then&nbsp;`p.wait()`&nbsp;blocks&nbsp;forever &nbsp;&nbsp;&nbsp;&nbsp;p.terminate()&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;p.wait()&nbsp;#&nbsp;wait&nbsp;for&nbsp;the&nbsp;process&nbsp;to&nbsp;terminate&nbsp;otherwise&nbsp;the&nbsp;output&nbsp;is&nbsp;garbled &nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;print&nbsp;saved&nbsp;output &nbsp;&nbsp;&nbsp;&nbsp;f.seek(0)&nbsp;#&nbsp;rewind&nbsp;to&nbsp;the&nbsp;beginning&nbsp;of&nbsp;the&nbsp;file &nbsp;&nbsp;&nbsp;&nbsp;print&nbsp;f.read(),&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;f.close()if&nbsp;__name__=="__main__": &nbsp;&nbsp;&nbsp;&nbsp;main()只打印输出部分的类似尾部的解决方案您可以在另一个线程中读取进程输出,并在队列中保存所需的最后一行数:import&nbsp;collectionsimport&nbsp;subprocessimport&nbsp;timeimport&nbsp;threadingdef&nbsp;read_output(process,&nbsp;append): &nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;line&nbsp;in&nbsp;iter(process.stdout.readline,&nbsp;""): &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;append(line)def&nbsp;main(): &nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;start&nbsp;process,&nbsp;redirect&nbsp;stdout &nbsp;&nbsp;&nbsp;&nbsp;process&nbsp;=&nbsp;subprocess.Popen(["top"],&nbsp;stdout=subprocess.PIPE,&nbsp;close_fds=True) &nbsp;&nbsp;&nbsp;&nbsp;try: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;save&nbsp;last&nbsp;`number_of_lines`&nbsp;lines&nbsp;of&nbsp;the&nbsp;process&nbsp;output &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;number_of_lines&nbsp;=&nbsp;200 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;q&nbsp;=&nbsp;collections.deque(maxlen=number_of_lines)&nbsp;#&nbsp;atomic&nbsp;.append() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t&nbsp;=&nbsp;threading.Thread(target=read_output,&nbsp;args=(process,&nbsp;q.append)) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t.daemon&nbsp;=&nbsp;True &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t.start() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;time.sleep(2) &nbsp;&nbsp;&nbsp;&nbsp;finally: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;process.terminate()&nbsp;#NOTE:&nbsp;it&nbsp;doesn't&nbsp;ensure&nbsp;the&nbsp;process&nbsp;termination &nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;print&nbsp;saved&nbsp;lines &nbsp;&nbsp;&nbsp;&nbsp;print&nbsp;''.join(q)if&nbsp;__name__=="__main__": &nbsp;&nbsp;&nbsp;&nbsp;main()这个变体需要q.append()成为原子操作。否则,输出可能损坏。signal.alarm()解你可以用signal.alarm()调用process.terminate()在指定超时后,而不是在另一个线程中读取。虽然它可能与subprocess模块。基于@Alex Martelli的回答:import&nbsp;collectionsimport&nbsp;signalimport&nbsp;subprocessclass&nbsp;Alarm(Exception): &nbsp;&nbsp;&nbsp;&nbsp;passdef&nbsp;alarm_handler(signum,&nbsp;frame): &nbsp;&nbsp;&nbsp;&nbsp;raise&nbsp;Alarmdef&nbsp;main(): &nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;start&nbsp;process,&nbsp;redirect&nbsp;stdout &nbsp;&nbsp;&nbsp;&nbsp;process&nbsp;=&nbsp;subprocess.Popen(["top"],&nbsp;stdout=subprocess.PIPE,&nbsp;close_fds=True) &nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;set&nbsp;signal&nbsp;handler &nbsp;&nbsp;&nbsp;&nbsp;signal.signal(signal.SIGALRM,&nbsp;alarm_handler) &nbsp;&nbsp;&nbsp;&nbsp;signal.alarm(2)&nbsp;#&nbsp;produce&nbsp;SIGALRM&nbsp;in&nbsp;2&nbsp;seconds &nbsp;&nbsp;&nbsp;&nbsp;try: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;save&nbsp;last&nbsp;`number_of_lines`&nbsp;lines&nbsp;of&nbsp;the&nbsp;process&nbsp;output &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;number_of_lines&nbsp;=&nbsp;200 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;q&nbsp;=&nbsp;collections.deque(maxlen=number_of_lines) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;line&nbsp;in&nbsp;iter(process.stdout.readline,&nbsp;""): &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;q.append(line) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;signal.alarm(0)&nbsp;#&nbsp;cancel&nbsp;alarm &nbsp;&nbsp;&nbsp;&nbsp;except&nbsp;Alarm: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;process.terminate() &nbsp;&nbsp;&nbsp;&nbsp;finally: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;print&nbsp;saved&nbsp;lines &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print&nbsp;''.join(q)if&nbsp;__name__=="__main__": &nbsp;&nbsp;&nbsp;&nbsp;main()这种方法只适用于*nix系统。如果process.stdout.readline()不会再回来了。threading.Timer解import&nbsp;collectionsimport&nbsp;subprocessimport&nbsp;threadingdef&nbsp;main(): &nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;start&nbsp;process,&nbsp;redirect&nbsp;stdout &nbsp;&nbsp;&nbsp;&nbsp;process&nbsp;=&nbsp;subprocess.Popen(["top"],&nbsp;stdout=subprocess.PIPE,&nbsp;close_fds=True) &nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;terminate&nbsp;process&nbsp;in&nbsp;timeout&nbsp;seconds &nbsp;&nbsp;&nbsp;&nbsp;timeout&nbsp;=&nbsp;2&nbsp;#&nbsp;seconds &nbsp;&nbsp;&nbsp;&nbsp;timer&nbsp;=&nbsp;threading.Timer(timeout,&nbsp;process.terminate) &nbsp;&nbsp;&nbsp;&nbsp;timer.start() &nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;save&nbsp;last&nbsp;`number_of_lines`&nbsp;lines&nbsp;of&nbsp;the&nbsp;process&nbsp;output &nbsp;&nbsp;&nbsp;&nbsp;number_of_lines&nbsp;=&nbsp;200 &nbsp;&nbsp;&nbsp;&nbsp;q&nbsp;=&nbsp;collections.deque(process.stdout,&nbsp;maxlen=number_of_lines) &nbsp;&nbsp;&nbsp;&nbsp;timer.cancel() &nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;print&nbsp;saved&nbsp;lines &nbsp;&nbsp;&nbsp;&nbsp;print&nbsp;''.join(q),if&nbsp;__name__=="__main__": &nbsp;&nbsp;&nbsp;&nbsp;main()这种方法也应该适用于Windows。我用过process.stdout作为一个可迭代的;它可能会引入一个额外的输出缓冲,您可以切换到iter(process.stdout.readline, "")如果这是不可取的,就接近它。如果进程未在process.terminate()然后脚本挂起。没有线程,没有信号解决方案import&nbsp;collectionsimport&nbsp;subprocessimport&nbsp;sysimport&nbsp;timedef&nbsp;main(): &nbsp;&nbsp;&nbsp;&nbsp;args&nbsp;=&nbsp;sys.argv[1:] &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;not&nbsp;args: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;args&nbsp;=&nbsp;['top'] &nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;start&nbsp;process,&nbsp;redirect&nbsp;stdout &nbsp;&nbsp;&nbsp;&nbsp;process&nbsp;=&nbsp;subprocess.Popen(args,&nbsp;stdout=subprocess.PIPE,&nbsp;close_fds=True) &nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;save&nbsp;last&nbsp;`number_of_lines`&nbsp;lines&nbsp;of&nbsp;the&nbsp;process&nbsp;output &nbsp;&nbsp;&nbsp;&nbsp;number_of_lines&nbsp;=&nbsp;200 &nbsp;&nbsp;&nbsp;&nbsp;q&nbsp;=&nbsp;collections.deque(maxlen=number_of_lines) &nbsp;&nbsp;&nbsp;&nbsp;timeout&nbsp;=&nbsp;2&nbsp;#&nbsp;seconds &nbsp;&nbsp;&nbsp;&nbsp;now&nbsp;=&nbsp;start&nbsp;=&nbsp;time.time()&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;(now&nbsp;-&nbsp;start)&nbsp;<&nbsp;timeout: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;line&nbsp;=&nbsp;process.stdout.readline() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;not&nbsp;line: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;q.append(line) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;now&nbsp;=&nbsp;time.time() &nbsp;&nbsp;&nbsp;&nbsp;else:&nbsp;#&nbsp;on&nbsp;timeout &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;process.terminate() &nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;print&nbsp;saved&nbsp;lines &nbsp;&nbsp;&nbsp;&nbsp;print&nbsp;''.join(q),if&nbsp;__name__=="__main__": &nbsp;&nbsp;&nbsp;&nbsp;main()这个变体既不使用线程,也不使用信号,但它在终端中产生错误的输出。如果process.stdout.readline()街区。

慕田峪4524236

我建议使用“ps”代替“top”,这将给您提供相同的信息,但只有一次,而不是一秒,在所有的永恒。您还需要在ps中使用一些标志,我倾向于使用“ps aux”

MMTTMM

我用另一种方法解决了。与直接在终端上输出不同,我将其转换为一个文件“tmp_file”:top&nbsp;>>&nbsp;tmp_file然后,我使用工具“剪切”使它的输出“是最高输出”作为过程的值。cat&nbsp;tmp_file它做了我想做的这是最后的代码:import&nbsp;osimport&nbsp;subprocessimport&nbsp;time subprocess.Popen("top&nbsp;>>&nbsp;tmp_file",shell&nbsp;=&nbsp;True)time.sleep(1)os.popen("killall&nbsp;top") process&nbsp;=&nbsp;os.popen("cat&nbsp;tmp_file").read()os.popen("rm&nbsp;tmp_file")print&nbsp;process#&nbsp;Thing&nbsp;better&nbsp;than&nbsp;nothing&nbsp;=)非常感谢你们的帮助
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python