python - 如何使用实时日志记录和超时选项实现 subprocess.Popen?
问题描述
我的目标是实现一个支持运行系统命令(使用子进程)的 Python 3 方法,满足以下几个要求:
- 运行持久的命令
- 标准输出和标准错误的实时记录
- 如果命令未能按时完成,则强制超时以停止命令
为了支持实时日志记录,我使用了 2 个线程来处理 stdout 和 stderr 输出。
我的挑战是强制线程和子进程进程超时。
我尝试使用信号处理程序实现超时,似乎在调用处理程序后立即冻结解释器。
我的实施有什么问题?
还有其他方法可以实现我的要求吗?
这是我当前的实现尝试:
def run_live_output(cmd, timeout=900, **kwargs):
full_output = StringIO()
def log_popen_pipe(p, log_errors=False):
while p.poll() is None:
output = ''
if log_errors:
output = p.stderr.readline()
log.warning(f"{output}")
else:
output = p.stdout.readline()
log.info(f"{output}")
full_output.write(output)
if p.poll():
log.error(f"{cmd}\n{p.stderr.readline()}")
class MyTimeout(Exception):
pass
def handler(signum, frame):
log.info(f"Signal handler called with signal {signum}")
raise MyTimeout
with subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
stdin=subprocess.PIPE,
universal_newlines=True,
**kwargs
) as sp:
with ThreadPoolExecutor(2) as pool:
try:
signal.signal(signal.SIGALRM, handler)
signal.alarm(timeout)
r1 = pool.submit(log_popen_pipe, sp)
r2 = pool.submit(log_popen_pipe, sp, log_errors=True)
r1.result()
r2.result()
except MyTimeout:
log.info(f"Timed out - Killing the threads and process")
pool.shutdown(wait=True)
sp.kill()
except Exception as e:
log.info(f"{e}")
return full_output.getvalue()
解决方案
推荐阅读
- r - 如何使用 Rblpapi 订阅功能创建数据框
- php - 带有 Bootstrap 多选样式的 Laravel 5.6
- java - 你能告诉我如何在spring boot 1.5.9.RELEASE中配置会话超时吗?
- javascript - Highcharts 和多图表提升
- java - 投票系统错误
- .net - 多个现有应用程序的通用应用程序
- sql - 创建一个存储过程,让我进行计算并将值插入 tempTable
- c# - ASP.NET Core 2.0 中的防伪 cookie
- python - TensorFlow Eager 的评估模式
- ubuntu - 在 Ubuntu 上构建的 Dotnet 返回代码 1