Catching Terminal Output in Python

2020-06-22 00:52发布

I want to do something similar to the second answer here (but not quite similar): Simulate Ctrl-C keyboard interrupt in Python while working in Linux

It's much simpler and I think I'm just missing something. Say, from a python script, I just want to call 'ping' and terminate it after the 10th time. I'm trying to do it like from the link above:

p = subprocess.Popen(['ping', 'google.com'], stdout=subprocess.PIPE)
for line in p.stdout:
  print line
  if re.search('10', line):
    break
os.kill(p.pid, signal.SIGINT)

But it doesn't work.

And I also want the regular output of 'ping' to be displayed. How do I do this?

EDIT: It's not actually a 'ping' that I want to do. I'm just using it as an example of a command with continuous output, which in time, I would like to terminate.

More specifically, I'm running an old version of BitTorrent (v5.0.9 from the 3rd answer here: Where to find BitTorrent source code?) and I'm calling it via python script. The bittorrent-console.py is a simple terminal version, hence 'console'. It outputs multiple lines periodically. Something like:

saving:       filename
file size:    blah
percent done: 100.0
blah:         blahblah

I'm actually calling it by:

subprocess.call(['./bittorrent-console.py', 'something.torrent'])

I want to terminate it automatically when I see it's 100.0 in 'percent done:'.

EDIT: I'm running on CentOS, Python 2.6.

2条回答
三岁会撩人
2楼-- · 2020-06-22 01:47

This does exactly what you want and works perfectly on my OS X machine:

import subprocess
import re

def get_output(cmd, until):
    p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
    ret = []
    while True:
        line = p.stdout.readline()
        ret.append(line)
        if re.search(until, line):
            break
    p.kill()
    return ret

 print ''.join(get_output(['ping', 'google.com'], until='10'))
查看更多
你好瞎i
3楼-- · 2020-06-22 01:58

Firstly, you want to use p.stdout.readline. I'm not sure why, but for line in p.stdout doesn't seem to flush. Perhaps it's buffered.

Secondly, you should use sys.stdout.write(line), because print always appends something. In Python 3 you can use print(line, end=""), though.

Also, you should prefer p.kill to os.kill. I'm not sure why you're using os.kill.

import os
import signal
import subprocess
import sys

p = subprocess.Popen(['ping', 'google.com'], stdout=subprocess.PIPE)
while True:
    line = p.stdout.readline()

    sys.stdout.write(line)
    sys.stdout.flush()
    if '10' in line:
        break

p.kill()
查看更多
登录 后发表回答