【Python】使用subprocess模块执行系统级别命令:程序异常处理

示例代码:

import subprocess
proc = subprocess.Popen(["/path/to/your/script"], shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
for line in iter(proc.stdout.readline, b''):
	print(line.decode(), end='')
proc.stdout.close()
proc.wait()

这段代码使用subproceess.Popen启动一个Shell进程来执行你的script。
shell=True表示通过操作系统的Shell来执行命令;
stdout=subprocess.PIPE表示将标准输出重定向到管道中,以便下一步处理,尽管示例中并没有下一步处理;
stderr=subprocess.STDOUT表示将标准错误输出与标准输出合并;
iter行语句使用迭代器逐行读取进程的标准输出,其中的b''表示空字节,iter()会持续读取,直到遇见空字节停止。
proc.stdout.close()关闭标准输出管道,表示标准输出读取完毕。
proc.wait()等待进程完成,并获取返回码。

如果你通过subprocess执行的脚本是某些易报错的程序,且在输出中会给出process id,那么你可以将这些pid捕获,然后再通过一个subprocess.run进程去执行kill它的命令,避免出错的程序干扰后面程序的自动执行;如果你的程序容易卡住,那么你可以使用signal模块设置一个定时器,结合try-except语句进行超时报警,并做处理。例如:

import subprocess
import signal

def handler():
	raise Exception("TIME UP!")

# 将信号处理函数handler与SIGALRM信号绑定,遇到SIGALRM信号时调用handler,也就是引发一个Exception
signal.signal(signal.SIGALRM, handler)  
try:
	signal.alarm(100)  # 开始计时100s
	try:
		proc = subprocess.Popen(["/path/to/your/script"], shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
		pid_list = []
		for line in iter(proc.stdout.readline, b''):
			print(line.decode(), end='')
			if "Process Id" in line.decode()
			pid = pid_line.split(":")
			pid = pid[1].strip()
			pid_list.append(pid)  # 获取涉及到的所有pid
		proc.stdout.close()
		proc.wait()
	except:
		try:
			for pid in pid_list:
				cmd = "kill -9" + pid
				subprocess.run(cmd, shell=True)  # 出错了之后把涉及到的进程都关掉
		except:
			pass  # 关不掉就算了
	signal.alarm(0)
except:  # 超时发送SIGALRM信号,引发Exception,进入下面的代码分支
	... # 处理超时情况的代码

上面这段代码总共嵌套了三层try-except语句。
第一层用来处理程序卡住的问题,也就是配合signal的计时器,在超时是引发一个Exception,进入except分支进行超时处理;
第二层用来处理程序出错的问题,在try中记录下所有涉及到的pid,如果报错,进入except进行kill操作;
第三层用来处理kill失败的情况,如果kill不成功就算了,当然也可以进行别的处理(一个充满故事的try-except

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值