如何使用 Python 3 停止线程内的 youtube-dl 下载

zaf*_*fer 5 python multithreading python-3.x youtube-dl

我有一个从特定 URL 下载视频的函数,我通过线程启动此函数以避免 GUI 冻结,但我想要一个函数来停止或暂停下载。这个怎么做?这是代码:

def download_videos(self):
     ydl1 = youtube_dl.YoutubeDL(self.get_opts())
     if self.get_Urls().__len__() > 0:
         ydl1.download(self.get_Urls())

def downloadVideoThrd(self):
    self.t1 = threading.Thread(target=self.download_videos())
    self.t1.start()
Run Code Online (Sandbox Code Playgroud)

Vey*_*gun 1

您可以使用这两个选项。使用multiprocessing库代替threadingSystemExit在子线程中引发异常

注意:当我测试 youtube-dl 时,它会从剩下的位置继续下载。这就是为什么当我们开始下载相同的网址时,youtube-dl 将恢复,但下载的文件需要位于文件系统中

这是第一个选项,在这个解决方案中,我们不使用线程,我们使用子进程,因为我们可以向子进程发送任何信号并根据需要处理该信号。

import multiprocessing
import time
import ctypes,signal,os
import youtube_dl

class Stop_Download(Exception): # This is our own special Exception class
    pass

def usr1_handler(signum,frame): # When signal comes, run this func
    raise Stop_Download

def download_videos(resume_event):
     signal.signal(signal.SIGUSR1,usr1_handler)

     def download(link):
         ydl1 = youtube_dl.YoutubeDL()
         ydl1.download([link])

     try:
         download(link)

     except Stop_Download: #catch this special exception and do what ever you want
         print("Stop_Download exception")
         resume_event.wait() # wait for event to resume or kill this process by sys.exit()
         print("resuming")
         download(link)

def downloadVideoThrd():
    resume_event=multiprocessing.Event()
    p1 = multiprocessing.Process(target=download_videos,args=(resume_event,))
    p1.start()
    print("mp start")
    time.sleep(5)
    os.kill(p1.pid,signal.SIGUSR1) # pause the download
    time.sleep(5)
    down_event.set() #resume downlaod
    time.sleep(5)
    os.kill(p1.pid,signal.SIGUSR2) # stop the download

downloadVideoThrd()
Run Code Online (Sandbox Code Playgroud)

这是第二种解决方案,您还可以检查以获取有关终止线程的更多详细信息。SystemExit我们将通过主线程在子线程中引发异常。我们可以停止或暂停线程。要暂停线程,您可以使用threading.Event()类。要停止线程(而不是进程),您可以使用sys.exit()

import ctypes,time, threading
import youtube_dl,

def download_videos(self):
    try:
        ydl1 = youtube_dl.YoutubeDL(self.get_opts())
        if self.get_Urls().__len__() > 0:
            ydl1.download(self.get_Urls())
    except SystemExit:
        print("stopped")
        #do whatever here

def downloadVideoThrd(self):
    self.t1 = threading.Thread(target=self.download_videos)
    self.t1.start()
    time.sleep(4)     
    """
    raise SystemExit exception in self.t1 thread
    """    
    ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(self.t1.ident),
                                            ctypes.py_object(SystemExit))
Run Code Online (Sandbox Code Playgroud)