我正在尝试在Python中开始使用多线程。我有多个线程获取锁,执行操作,释放锁,并将结果输出到csv文件。如果主线程完成,则应终止线程(例如,通过按Ctrl + C)。这是怎么做到的?
我认为使线程守护进程应该完成这项工作,因为“当只剩下守护进程线程时,整个Python程序退出”(官方Python文档)。这还不够。根据{{3}},然后我尝试捕获KeyboardInterrupt,然后手动终止线程。这也不起作用,似乎没有正确捕获KeyboardInterrupt。
这让我觉得,在Python中有一些关于多线程的东西,我误解了......找到附加的代码:
import random
import csv
import sys
from datetime import datetime
import threading
lock = threading.Lock()
def observer(obs):
print("In " + str(obs))
sys.stdout.flush()
with open("data/test_" + str(obs) + ".csv", 'a', newline='') as csvfile:
while True:
datenow = datetime.today()
lock.acquire()
print(str(obs) + "acquired")
sum = 0
for i in range(10000):
sum = sum + random.random()
print(str(obs) + "released")
sys.stdout.flush()
lock.release()
writer = csv.writer(csvfile, delimiter=',', quoting=csv.QUOTE_ALL)
writer.writerow([datenow.isoformat(), sum/10000])
#print(str(obs) + ": " + datenow.isoformat() + " " + str(sum/1000))
sys.stdout.flush()
if __name__ == "__main__":
observe = [1, 2, 3, 4]
processes = []
for obs in observe:
process = threading.Thread(target=observer, args=(obs,), daemon=True)
processes.append(process)
print("Start processes")
for p in processes:
p.start()
print("Started")
try:
for p in processes:
p.join()
except KeyboardInterrupt:
for p in processes:
p.terminate()
print("Keyboard interrupt")
print("Finished")
谢谢!
答案 0 :(得分:0)
错误
try:
for p in processes:
p.join()
except KeyboardInterrupt:
for p in processes:
p.terminate()
print("Keyboard interrupt")
您的主题永远不会退出while True:
循环,因此您将永远加入它们。但那不是重点。
如果没有抓住Ctrl-C
(又名KeyboardInterrupt
),我最好的选择是:
Ctrl-C
因为您的程序被突然终止。你的问题是:
如果上述假设是正确的,请尝试使用此代码(来自Python - Windows - Exiting Child Process when "unrelated" parent dies/crashes)
import sys
def win_wait_for_parent(raise_exceptions=False):
if not sys.platform == 'win32':
return True
# When started under cygwin, the parent process will die leaving a child
# hanging around. The process has to be waited upon
import ctypes
from ctypes.wintypes import DWORD, BOOL, HANDLE
import os
import threading
INFINITE = -1
SYNCHRONIZE = 0x00100000
kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
kernel32.OpenProcess.argtypes = (DWORD, BOOL, DWORD)
kernel32.OpenProcess.restype = HANDLE
kernel32.WaitForSingleObject.argtypes = (HANDLE, DWORD)
kernel32.WaitForSingleObject.restype = DWORD
phandle = kernel32.OpenProcess(SYNCHRONIZE, 0, os.getppid())
def check_parent():
# Get a token with right access to parent and wait for it to be
# signaled (die). Exit ourselves then
kernel32.WaitForSingleObject(phandle, INFINITE)
os._exit(0)
if not phandle:
if raise_exceptions:
raise ctypes.WinError(ctypes.get_last_error())
return False