我试图弄清楚如何使用Python在Windows上正确发送CTRL-C信号。早些时候我正在搞乱youtube-dl并将其嵌入到PyQt Qthread中进行处理并创建了一个停止按钮来停止线程但是在尝试下载直播时我甚至无法让FFMPEG在关闭应用程序后停止我必须手动杀死每次都打破视频的过程 我知道我必须以某种方式向它发送一个CTRL-C信号并最终使用它。
os.kill(signal.CTRL_C_EVENT, 0)
我实际上能够让它工作但是如果你尝试下载多个视频并尝试使用上述信号停止其中一个线程,则会终止所有下载。
有没有办法将信号发送到一个线程而不影响其他线程?
下面是一些带有2个单独线程的常规Python代码的示例,其中10秒后在thread_2中触发CTRL-C信号,最终导致thread_1死亡。
import os
import signal
import threading
import time
import youtube_dl
def thread_1():
print("thread_1 running")
url = 'https://www.cbsnews.com/common/video/cbsn_header_prod.m3u8'
path = 'C:\\Users\\Richard\\Desktop\\'
ydl_opts = {
'format': 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best',
'outtmpl': '{0}%(title)s-%(id)s.%(ext)s'.format(path),
'nopart': True,
}
ydl_opts = ydl_opts
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
try:
ydl.download([url])
except KeyboardInterrupt:
print('stopped')
def thread_2():
print("thread_2 running")
time.sleep(10)
os.kill(signal.CTRL_C_EVENT, 0)
def launch_thread(target, message, args=[], kwargs={}):
def thread_msg(*args, **kwargs):
target(*args, **kwargs)
print(message)
thread = threading.Thread(target=thread_msg, args=args, kwargs=kwargs)
thread.start()
return thread
if __name__ == '__main__':
thread1 = launch_thread(thread_1, "finished thread_1")
thread2 = launch_thread(thread_2, "finished thread_2")
有没有人有任何建议或想法?感谢。
答案 0 :(得分:1)
无法将信号发送到另一个线程,因此您需要执行其他操作。
你可能会在另一个线程中引发异常,使用这个hack(我不会在这里复制源代码,因为它附带了MIT许可证): http://tomerfiliba.com/recipes/Thread2/
有了这个,你可以向另一个线程发送一个KeyboardInterrupt异常,这就是Ctrl-C无论如何。
虽然看起来这样做可以做到你想要的,但它仍会破坏当前正在下载的视频。
另一方面,因为你似乎只对主线程退出时杀死所有线程感兴趣,所以可以用更简单的方式完成:
将所有线程配置为daemons,例如:
thread = threading.Thread(target=thread_msg, args=args, kwargs=kwargs)
thread.daemon = True
thread.start()
这些线程将在主线程退出时退出,无需您进行任何其他干预。
答案 1 :(得分:0)
有没有办法将信号发送到一个线程而不影响其他线程?
我不是Python专家,但如果我试图解决您的问题,在阅读了signal handling in Python3后,我会开始计划使用多个进程,而不是在一个进程中使用多个线程。