ben*_*sop 6 python error-handling microcontroller multiprocessing pytest
如何测试我的程序对于意外关闭的鲁棒性?
我的 python 代码将在意外关闭的微控制器上运行。我想测试意外重新启动的代码的每个部分,并验证它是否正确处理此问题。
尝试:我尝试将代码放入其自己的进程中,然后提前终止它,但这不起作用,因为 MyClass 从命令行调用 7zip,即使进程终止后,该命令仍会继续:
import multiprocessing
import os
def MyClass(multiprocessing.Process):
...
def run():
os.system("7z a myfile.7z myfile")
process = MyClass()
process.start()
time.sleep(4)
print("terminating early")
process.terminate()
print("done")
Run Code Online (Sandbox Code Playgroud)
我想要的是:
class TestMyClass(unittest.TestCase):
def test_MyClass_continuity(self):
myclass = MyClass().start()
myclass.kill_everything()
myclass = MyClass().start()
self.assert_everything_worked_as_expected()
Run Code Online (Sandbox Code Playgroud)
是否有捷径可寻?如果没有,您如何设计可以在任何点终止的健壮代码(例如测试状态机)?
类似的问题(截至 21 年 10 月 26 日尚未回答):Simizing异常终止 in pytest
多谢!
您的逻辑启动一个包装在MyClass对象内的进程,该对象本身通过调用生成一个新进程os.system。
当您终止MyClass进程时,您会终止父进程,但会让该7zip进程作为孤立进程运行。
此外,该方法还向子进程process.terminate发送信号。SIGTERM子进程可以拦截所述信号并在终止之前执行一些清理例程。如果您想模拟没有机会清理的情况(断电),这并不理想。您很可能想发送一个SIGKILL信号(在 Linux 上)。
要杀死父进程和子进程,需要处理整个进程组。
import os
import time
import signal
import multiprocessing
class MyClass(multiprocessing.Process):
def run(self):
# Ping localhost for a limited amount of time
os.system("ping -c 12 127.0.0.1")
process = MyClass()
process.start()
time.sleep(4)
print("terminating early")
# Send SIGKILL signal to the entire process group
group_id = os.getpgid(process.pid)
os.killpg(group_id, signal.SIGKILL)
print("done")
Run Code Online (Sandbox Code Playgroud)
以上仅适用于 Unix 操作系统,不适用于 Windows 操作系统。
对于 Windows,您需要使用psutil模块。
import os
import time
import multiprocessing
import psutil
class MyClass(multiprocessing.Process):
def run(self):
# Ping localhost for a limited amount of time
os.system("ping -c 12 127.0.0.1")
def kill_process_group(pid):
process = psutil.Process(pid)
children = process.children(recursive=True)
# First terminate all children
for child in children:
child.kill()
psutil.wait_procs(children)
# Then terminate the parent process
process.kill()
process.wait()
process = MyClass()
process.start()
time.sleep(4)
print("terminating early")
kill_process_group(process.pid)
print("done")
Run Code Online (Sandbox Code Playgroud)