我有这个遗留代码,我想为其添加错误处理。令我惊讶的是,我发现其中的 try 和 except 不起作用。经过一番调试后,发现这是因为
signal.signal(signal.SIGCHLD, signal.SIG_IGN)
代码使主进程忽略了子异常。所以在原来的代码中,永远不会到达except subprocess.CalledProcessError as e:
。我怀疑以前的程序员是否正确完成了此操作,并且我想删除 signal.signal(signal.SIGCHLD, signal.SIG_IGN)
行,以便 try...except
能够按预期工作。但我不知道这是否会在处理子进程时造成任何麻烦。(例如,我不知道创建的僵尸子进程)。有什么修改建议吗?
import threading
import logging
import queue
import subprocess
import signal
class Worker(threading.Thread):
def __init__(self, thread_id, work_queue):
threading.Thread.__init__(self)
self._thread_id = thread_id
self._queue = work_queue
def run(self):
while not self._queue.empty():
module = self._queue.get()
try:
subprocess.run(["python3.8", module], check=True)
except subprocess.CalledProcessError as e:
logging.error(
"Worker: {} failed to process '{}'. Error: {}".format(
self._thread_id,
module.split("/")[-1], e))
self._queue.task_done()
logging.info("Worker: {} has exited!".format(self._thread_id))
def process_modules(modules):
modulesQueue = queue.Queue()
for i in modules:
modulesQueue.put(i)
workers = []
for i in range(1):
worker = Worker(i,
modulesQueue) # create a worker for each available GPU
workers.append(worker)
worker.start() # start the worker
modulesQueue.join() # wait for all modules to be processed
def validate_models():
modules = ["case1", "case2"]
process_modules(modules)
return modules
if __name__ == "__main__":
# Ignore SIGCHLD handler to not creating zombie child processes.
signal.signal(signal.SIGCHLD, signal.SIG_IGN)
validate_models()
这里不需要任何信号处理。也不需要排队。实在是太复杂了。下面是一些代码,只需几行即可实现相同的功能:
from concurrent.futures import ThreadPoolExecutor
import logging
import subprocess
PYTHON = "/Library/Frameworks/Python.framework/Versions/3.12/bin/python3"
def process(module):
try:
subprocess.run([PYTHON, module], check=True)
except subprocess.CalledProcessError as e:
logging.error(f"Module {module} failed due to {e}")
def main():
modules = ["module1.py", "module2.py"]
with ThreadPoolExecutor() as exe:
exe.map(process, modules)
if __name__ == "__main__":
main()
这里唯一的潜在问题是被调用的“模块”是否被卡住。您必须编写一些相当复杂的代码来管理这种可能性