Python:使用子流程执行长时间运行的流程.Popen,杀死它,并获取它的输出



我正试图以root身份运行一个"长时间运行"的进程(因为我必须这样做(,在线程中,在python中,然后杀死它,然后访问它的输出。

有问题的进程是"babeld",当我在终端中启动它时,它会在stdout上输出文本。然而,当我运行以下代码时,我无法访问stderr或stdout:

% ./example.py                                                                                                                                                                                                                                                                                   
Waiting for output
Pgid: 13445, pid: 13445
Stopping task
Permission Error!
Calling sudo kill 13445
B
None
None
End

代码:

#!/usr/bin/env python3
import subprocess
import threading
import time
import os
def main():
task = TaskManager()
task.launch()
time.sleep(2)
task.stop()
print(task.stdout)
print(task.stderr)

class TaskManager(threading.Thread):
def __init__(self):
super().__init__()
self.start_event = threading.Event()
self.stderr = None
self.stdout = None
self.pgid = None
self.task = None
self.start()

def run(self):
self.start_event.wait()
self.task = subprocess.Popen(["sudo", "babeld", "-d", "2", "wlp2s0"],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
preexec_fn=os.setsid)
self.pgid = os.getpgid(self.task.pid)
print("Waiting for output")
self.stdout, self.stderr = self.task.communicate()
print("End")
def launch(self):
self.start_event.set()
def stop(self):
print("Pgid: %s, pid: %s" % (self.pgid, self.task.pid))
try:
print("Stopping task")
self.task.terminate()
except PermissionError:
print("Permission Error!")
print("Calling sudo kill %d" % self.pgid)
subprocess.check_call(["sudo", "kill", str(self.pgid)])
print("B")
if __name__ == '__main__':
main()

如何正确地杀死以root身份运行的进程,同时访问它们的stderr和stdout?

谢谢,

配方很简单:不要使用communicate。您可以用以下getter替换self.stdoutself.stderr类属性:

@property
def stdout(self):
return self.task.stdout.read()
@property
def stderr(self):
return self.task.stderr.read()

顺便说一句,这种方法为您提供了一个拒绝在代码中使用线程的机会。示例:

# !/usr/bin/env python3
import subprocess
import time
import os

def main():
task = TaskManager()
task.launch()
time.sleep(2)
task.stop()
print(task.stdout)
print(task.stderr)

class TaskManager:
def __init__(self):
self.pgid = None
self.task = None
@property
def stdout(self):
return self.task.stdout.read()
@property
def stderr(self):
return self.task.stderr.read()
def launch(self):
self.task = subprocess.Popen(["sudo", "babeld", "-d", "2", "wlp2s0"],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
preexec_fn=os.setsid)
self.pgid = os.getpgid(self.task.pid)
print("Waiting for output")
def stop(self):
print("Pgid: %s, pid: %s" % (self.pgid, self.task.pid))
try:
print("Stopping task")
self.task.terminate()
except PermissionError:
print("Permission Error!")
print("Calling sudo kill %d" % self.pgid)
subprocess.check_call(["sudo", "kill", str(self.pgid)])
print("B")

if __name__ == '__main__':
main()

最新更新