打印时无法终止由 Popen 创建的子进程 process.stdout
cannot kill a Sub process created by Popen when printing process.stdout
我创建了一个脚本,它应该运行一个命令并在 15 秒后终止它
import logging
import subprocess
import time
import os
import sys
import signal
#cmd = "ping 192.168.1.1 -t"
cmd = "C:\MyAPP\MyExe.exe -t 80 -I C:\MyApp\Temp -M Documents"
proc=subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,shell=True)
**for line in proc.stdout:
print (line.decode("utf-8"), end='')**
time.sleep(15)
os.kill(proc.pid, signal.SIGTERM)
#proc.kill() #Tried this too but no luck
这不会终止我的子进程。但是,如果我注释掉日志记录到标准输出部分,即
for line in proc.stdout:
print (line.decode("utf-8"), end='')
子进程已被终止。
我也试过 proc.kill() and CTRL_C_EVENT
但没有成功。
任何帮助将不胜感激。请将我视为python
的新手
问题是从 stdout 读取被阻塞。您需要读取子进程的输出或 运行 单独线程上的计时器。
from subprocess import Popen, PIPE
from threading import Thread
from time import sleep
class ProcKiller(Thread):
def __init__(self, proc, time_limit):
super(ProcKiller, self).__init__()
self.proc = proc
self.time_limit = time_limit
def run(self):
sleep(self.time_limit)
self.proc.kill()
p = Popen('while true; do echo hi; sleep 1; done', shell=True)
t = ProcKiller(p, 5)
t.start()
p.communicate()
已编辑以反映评论中建议的更改
from subprocess import Popen, PIPE
from threading import Thread
from time import sleep
from signal import SIGTERM
import os
class ProcKiller(Thread):
def __init__(self, proc, time_limit):
super(ProcKiller, self).__init__()
self.proc = proc
self.time_limit = time_limit
def run(self):
sleep(self.time_limit)
os.kill(self.proc.pid, SIGTERM)
p = Popen('while true; do echo hi; sleep 1; done', shell=True)
t = ProcKiller(p, 5)
t.start()
p.communicate()
在逐行打印其输出的同时在 15 秒内终止子进程:
#!/usr/bin/env python
from __future__ import print_function
from threading import Timer
from subprocess import Popen, PIPE, STDOUT
# start process
cmd = r"C:\MyAPP\MyExe.exe -t 80 -I C:\MyApp\Temp -M Documents"
process = Popen(cmd, stdout=PIPE, stderr=STDOUT,
bufsize=1, universal_newlines=True)
# terminate process in 15 seconds
timer = Timer(15, terminate, args=[process])
timer.start()
# print output
for line in iter(process.stdout.readline, ''):
print(line, end='')
process.stdout.close()
process.wait() # wait for the child process to finish
timer.cancel()
注意,这里不需要 shell=True
。您可以将 terminate()
定义为:
def terminate(process):
if process.poll() is None:
try:
process.terminate()
except EnvironmentError:
pass # ignore
如果你想杀死整个进程树然后定义 terminate()
为:
from subprocess import call
def terminate(process):
if process.poll() is None:
call('taskkill /F /T /PID ' + str(process.pid))
- 对 Windows 路径使用原始字符串文字:
r""
否则你应该转义字符串文字中的所有反斜杠
- 放弃
shell=True
。它在这里无缘无故地创建了一个额外的进程
universal_newlines=True
启用文本模式(在 Python 3 上自动使用区域设置首选编码将字节解码为 Unicode 文本)
iter(process.stdout.readline, '')
是与 Python 2 兼容所必需的(否则由于预读缓冲区错误,数据可能会延迟打印)
- 使用
process.terminate()
代替process.send_signal(signal.SIGTERM)
或os.kill(proc.pid, signal.SIGTERM)
taskkill
允许在 Windows 上终止进程树
我创建了一个脚本,它应该运行一个命令并在 15 秒后终止它
import logging
import subprocess
import time
import os
import sys
import signal
#cmd = "ping 192.168.1.1 -t"
cmd = "C:\MyAPP\MyExe.exe -t 80 -I C:\MyApp\Temp -M Documents"
proc=subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,shell=True)
**for line in proc.stdout:
print (line.decode("utf-8"), end='')**
time.sleep(15)
os.kill(proc.pid, signal.SIGTERM)
#proc.kill() #Tried this too but no luck
这不会终止我的子进程。但是,如果我注释掉日志记录到标准输出部分,即
for line in proc.stdout:
print (line.decode("utf-8"), end='')
子进程已被终止。
我也试过 proc.kill() and CTRL_C_EVENT
但没有成功。
任何帮助将不胜感激。请将我视为python
问题是从 stdout 读取被阻塞。您需要读取子进程的输出或 运行 单独线程上的计时器。
from subprocess import Popen, PIPE
from threading import Thread
from time import sleep
class ProcKiller(Thread):
def __init__(self, proc, time_limit):
super(ProcKiller, self).__init__()
self.proc = proc
self.time_limit = time_limit
def run(self):
sleep(self.time_limit)
self.proc.kill()
p = Popen('while true; do echo hi; sleep 1; done', shell=True)
t = ProcKiller(p, 5)
t.start()
p.communicate()
已编辑以反映评论中建议的更改
from subprocess import Popen, PIPE
from threading import Thread
from time import sleep
from signal import SIGTERM
import os
class ProcKiller(Thread):
def __init__(self, proc, time_limit):
super(ProcKiller, self).__init__()
self.proc = proc
self.time_limit = time_limit
def run(self):
sleep(self.time_limit)
os.kill(self.proc.pid, SIGTERM)
p = Popen('while true; do echo hi; sleep 1; done', shell=True)
t = ProcKiller(p, 5)
t.start()
p.communicate()
在逐行打印其输出的同时在 15 秒内终止子进程:
#!/usr/bin/env python
from __future__ import print_function
from threading import Timer
from subprocess import Popen, PIPE, STDOUT
# start process
cmd = r"C:\MyAPP\MyExe.exe -t 80 -I C:\MyApp\Temp -M Documents"
process = Popen(cmd, stdout=PIPE, stderr=STDOUT,
bufsize=1, universal_newlines=True)
# terminate process in 15 seconds
timer = Timer(15, terminate, args=[process])
timer.start()
# print output
for line in iter(process.stdout.readline, ''):
print(line, end='')
process.stdout.close()
process.wait() # wait for the child process to finish
timer.cancel()
注意,这里不需要 shell=True
。您可以将 terminate()
定义为:
def terminate(process):
if process.poll() is None:
try:
process.terminate()
except EnvironmentError:
pass # ignore
如果你想杀死整个进程树然后定义 terminate()
为:
from subprocess import call
def terminate(process):
if process.poll() is None:
call('taskkill /F /T /PID ' + str(process.pid))
- 对 Windows 路径使用原始字符串文字:
r""
否则你应该转义字符串文字中的所有反斜杠 - 放弃
shell=True
。它在这里无缘无故地创建了一个额外的进程 universal_newlines=True
启用文本模式(在 Python 3 上自动使用区域设置首选编码将字节解码为 Unicode 文本)iter(process.stdout.readline, '')
是与 Python 2 兼容所必需的(否则由于预读缓冲区错误,数据可能会延迟打印)- 使用
process.terminate()
代替process.send_signal(signal.SIGTERM)
或os.kill(proc.pid, signal.SIGTERM)
taskkill
允许在 Windows 上终止进程树