在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 問答/Python/ 我想問一下,tkinter 做多線程爬蟲,讓他停止該怎么做 quit 和 exi

我想問一下,tkinter 做多線程爬蟲,讓他停止該怎么做 quit 和 exit 都是直接退出程序

    thread = threading.Thread(target=self.threading_run);
    thread.start()

    pass
def threading_run_s(self):

    print("-----------****************++++++++")
    print(url)
    for xb in range(10):
        print(xb)
        output.Output(str(xb))
        time.sleep(10)
        
回答
編輯回答
有點壞

python 沒有現(xiàn)成的方法可以強制結束線程,建議改用 multiprocessing 模塊。


強制結束線程可通過 ctypes 調(diào)用系統(tǒng) API 實現(xiàn),以 windows 系統(tǒng)為例,如下

# -*- coding: utf-8 -*-
import threading
import time
from datetime import datetime


def term_thread(thread_id):
    # 強制結束線程
    import os
    if os.name == "nt":
        # windows 系統(tǒng)
        # 注意:線程結束后 threading.Thread 沒有任何提示。
        import ctypes
        h = ctypes.windll.kernel32.OpenThread(1, 0, thread_id)
        assert h != 0
        r = ctypes.windll.kernel32.TerminateThread(h, 0xff)
        assert r != 0
    else:
        # TODO
        raise NotImplementedError


def run_thread():
    while 1:
        time.sleep(1)
        print('{}'.format(datetime.now()))


def main():
    t = threading.Thread(target=run_thread)
    t.start()

    time.sleep(3)
    term_thread(t.ident)

    # 強制結束線程導致 join() 永遠不會返回
    # t.join()


if __name__ == '__main__':
    main()
2017年4月4日 10:53
編輯回答
賤人曾

Python的threading類沒有提供退出方法,退出方法需要自己實現(xiàn).
這涉及到兩個問題:

  • 線程通信:子線程怎么知道父線程讓子線程退出.
  • 退出的實現(xiàn):子線程知道之后該怎么退出

線程通信

threading提供了Event這個類,實際上這個類就是一個信號,可以比較方便的實現(xiàn)線程間通信.因為多線程運行在一個進程中,也可以自己定義一個類來傳遞信號.略過不表.

# coding:utf-8
import threading
import time

signal = threading.Event()  # 定義一個信號


def worker(signal, *args, **kwargs):
    """子線程核心函數(shù)

    Arguments:
        signal {threading.Event} -- 接收的信號
    """
    # 如果信號為False,則執(zhí)行任務
    while not signal.isSet():
        # 執(zhí)行工作
        print("working")
        time.sleep(1)

    print("exiting")
    # 信號為True時,退出子線程
    exit()


t = threading.Thread(target=worker, args=(signal,))
t.start()
time.sleep(2)
print(u"發(fā)送退出信號")
signal.set()
time.sleep(1.5)
print(u"當前子線程的狀態(tài)為{}".format(t.isAlive()))
time.sleep(1)

輸出

working
working
發(fā)送退出信號
exiting
當前子線程的狀態(tài)為False

在子線程內(nèi)部調(diào)用exit(),是退出子線程而不是退出主線程,調(diào)用位置的問題.

退出線程

退出線程有很多辦法,不過核心就是判斷信號的狀態(tài).這就需要在worker流程控制中加好判斷點位.要明確退出不是指令發(fā)出去立刻就會執(zhí)行,而是處理信號的代碼發(fā)現(xiàn)了信號改變才會停止worker,這個是需要自己實現(xiàn)的.
比如上方代碼在signal.isSet()發(fā)生改變之后,跳出了while循環(huán),實際上worker已經(jīng)結束了,exit方法是為了增加可讀性的,完全沒必要加.
通過任何方法結束線程都可以,運行完畢或者手動exit都可以

2018年6月24日 00:42