搜尋
首頁後端開發Python教學Python執行緒中定位與銷毀的詳細介紹(附範例)

這篇文章帶給大家的內容是關於Python線程中定位與銷毀的詳細介紹(附示例),有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。

開工前我就覺得有什麼不太對勁,感覺要背鍋。這可不,上班第三天就捅鍋了。

我們有個了不起的後台程序,可以動態載入模組,並以執行緒方式運行,透過這種形式實現外掛程式的功能。而模組更新時候,後台程式本身不會退出,只會將模組對應的執行緒關閉、更新程式碼再啟動,6 得不行。

於是乎我就寫了個模組準備大展身手,結果忘記寫退出函數了,導致每次更新模組都新創建一個線程,除非重啟那個程序,否則那些線程就一直苟活著。

這可不行啊,得想個辦法清理呀,要不然怕是要炸了。

那麼怎麼清理呢?我能想到的就是兩步走:

  1. 找出需要清理的線程號tid;

  2. 銷毀它們;

找出線程ID

和平時的故障排查相似,先透過ps 指令看看目標行程的執行緒情況,因為已經是setName 設定過執行緒名,所以正常來說應該是看到對應的線程的。直接用下面程式​​碼來模擬這個執行緒:

Python 版本的多執行緒

#coding: utf8
import threading
import os
import time

def tt():
    info = threading.currentThread()
    while True:
        print 'pid: ', os.getpid()
        print info.name, info.ident
        time.sleep(3)

t1 = threading.Thread(target=tt)
t1.setName('OOOOOPPPPP')
t1.setDaemon(True)
t1.start()

t2 = threading.Thread(target=tt)
t2.setName('EEEEEEEEE')
t2.setDaemon(True)
t2.start()


t1.join()
t2.join()

#輸出:

root@10-46-33-56:~# python t.py
pid:  5613
OOOOOPPPPP 139693508122368
pid:  5613
EEEEEEEEE 139693497632512
...

可以看到在Python 裡面輸出的執行緒名稱就是我們設定的那樣,然而Ps 的結果卻是令我懷疑人生:

root@10-46-33-56:~# ps -Tp 5613
  PID  SPID TTY          TIME CMD
 5613  5613 pts/2    00:00:00 python
 5613  5614 pts/2    00:00:00 python
 5613  5615 pts/2    00:00:00 python

正常來說不該是這樣呀,我有點迷了,難道我一直都是記錯了?用別的語言版本的多執行緒來測試下:

C 版本的多執行緒

#include<stdio.h>
#include<sys>
#include<sys>
#include<pthread.h>

void *test(void *name)
{    
    pid_t pid, tid;
    pid = getpid();
    tid = syscall(__NR_gettid);
    char *tname = (char *)name;
    
    // 设置线程名字
    prctl(PR_SET_NAME, tname);
    
    while(1)
    {
        printf("pid: %d, thread_id: %u, t_name: %s\n", pid, tid, tname);
        sleep(3);
    }
}

int main()
{
    pthread_t t1, t2;
    void *ret;
    pthread_create(&t1, NULL, test,  (void *)"Love_test_1");
    pthread_create(&t2, NULL, test,  (void *)"Love_test_2");
    pthread_join(t1, &ret);
    pthread_join(t2, &ret);
}</pthread.h></sys></sys></stdio.h>

輸出:

root@10-46-33-56:~# gcc t.c -lpthread && ./a.out
pid: 5575, thread_id: 5577, t_name: Love_test_2
pid: 5575, thread_id: 5576, t_name: Love_test_1
pid: 5575, thread_id: 5577, t_name: Love_test_2
pid: 5575, thread_id: 5576, t_name: Love_test_1
...

用PS 指令再次驗證:

root@10-46-33-56:~# ps -Tp 5575
  PID  SPID TTY          TIME CMD
 5575  5575 pts/2    00:00:00 a.out
 5575  5576 pts/2    00:00:00 Love_test_1
 5575  5577 pts/2    00:00:00 Love_test_2

這個才是正確嘛,線程名確實是可以透過Ps 看出來的嘛!

不過為啥 Python 那個看不到呢?既然是透過setName 設定線程名的,那就看看定義咯:

[threading.py]
class Thread(_Verbose):
    ...
    @property
    def name(self):
        """A string used for identification purposes only.

        It has no semantics. Multiple threads may be given the same name. The
        initial name is set by the constructor.

        """
        assert self.__initialized, "Thread.__init__() not called"
        return self.__name

    @name.setter
    def name(self, name):
        assert self.__initialized, "Thread.__init__() not called"
        self.__name = str(name)
        
    def setName(self, name):
        self.name = name
    ...

看到這裡其實只是在Thread 物件的屬性設定了而已,並沒有動到根本,那肯定就是看不到咯~

這樣看起來,我們已經沒辦法透過ps/proc/ 這類手段在外部搜尋python 線程名了,所以我們只能在Python 內部來解決。

於是問題就變成了,怎麼能在 Python 內部拿到所有正在執行的執行緒呢?

threading.enumerate  可以完美解決這個問題! Why?

Because 在下面這個函數的 doc 裡面說得很清楚了,傳回所有活躍的執行緒物件,不包括終止和未啟動的。

[threading.py]

def enumerate():
    """Return a list of all Thread objects currently alive.

    The list includes daemonic threads, dummy thread objects created by
    current_thread(), and the main thread. It excludes terminated threads and
    threads that have not yet been started.

    """
    with _active_limbo_lock:
        return _active.values() + _limbo.values()

因為拿到的是 Thread 的對象,所以我們透過這個能到該線程相關的資訊!

請看完整程式碼範例:

#coding: utf8

import threading
import os
import time


def get_thread():
    pid = os.getpid()
    while True:
        ts = threading.enumerate()
        print '------- Running threads On Pid: %d -------' % pid
        for t in ts:
            print t.name, t.ident
        print
        time.sleep(1)
        
def tt():
    info = threading.currentThread()
    pid = os.getpid()
    while True:
        print 'pid: {}, tid: {}, tname: {}'.format(pid, info.name, info.ident)
        time.sleep(3)
        return

t1 = threading.Thread(target=tt)
t1.setName('Thread-test1')
t1.setDaemon(True)
t1.start()

t2 = threading.Thread(target=tt)
t2.setName('Thread-test2')
t2.setDaemon(True)
t2.start()

t3 = threading.Thread(target=get_thread)
t3.setName('Checker')
t3.setDaemon(True)
t3.start()

t1.join()
t2.join()
t3.join()

輸出:

root@10-46-33-56:~# python t_show.py
pid: 6258, tid: Thread-test1, tname: 139907597162240
pid: 6258, tid: Thread-test2, tname: 139907586672384

------- Running threads On Pid: 6258 -------
MainThread 139907616806656
Thread-test1 139907597162240
Checker 139907576182528
Thread-test2 139907586672384

------- Running threads On Pid: 6258 -------
MainThread 139907616806656
Thread-test1 139907597162240
Checker 139907576182528
Thread-test2 139907586672384

------- Running threads On Pid: 6258 -------
MainThread 139907616806656
Thread-test1 139907597162240
Checker 139907576182528
Thread-test2 139907586672384

------- Running threads On Pid: 6258 -------
MainThread 139907616806656
Checker 139907576182528
...

程式碼看起來有點長,但是邏輯相當簡單,Thread-test1Thread-test2 都是印出目前的pid、執行緒id 和執行緒名字,然後3s 後退出,這個是想模擬執行緒正常退出。

Checker 執行緒則是每秒透過 threading.enumerate 輸出目前行程內所有活躍的執行緒。

可以明顯看到一開始是可以看到Thread-test1Thread-test2的訊息,當它兩個退出之後就只剩下 MainThreadChecker 本身而已了。

銷毀指定執行緒

既然能拿到名字和執行緒 id,那我們也就能幹掉指定的執行緒了!

假設現在Thread-test2 已經黑化,發瘋了,我們需要阻止它,那我們就可以透過這種方式解決了:

在上面的程式碼基礎上,增加和補上下列程式碼:

def _async_raise(tid, exctype):
    """raises the exception, performs cleanup if needed"""
    tid = ctypes.c_long(tid)
    if not inspect.isclass(exctype):
        exctype = type(exctype)
    res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))
    if res == 0:
        raise ValueError("invalid thread id")
    elif res != 1:
        ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)
        raise SystemError("PyThreadState_SetAsyncExc failed")

def stop_thread(thread):
    _async_raise(thread.ident, SystemExit)

def get_thread():
    pid = os.getpid()
    while True:
        ts = threading.enumerate()
        print '------- Running threads On Pid: %d -------' % pid
        for t in ts:
            print t.name, t.ident, t.is_alive()
            if t.name == 'Thread-test2':
                print 'I am go dying! Please take care of yourself and drink more hot water!'
                stop_thread(t)
        print
        time.sleep(1)

輸出

root@10-46-33-56:~# python t_show.py
pid: 6362, tid: 139901682108160, tname: Thread-test1
pid: 6362, tid: 139901671618304, tname: Thread-test2
------- Running threads On Pid: 6362 -------
MainThread 139901706389248 True
Thread-test1 139901682108160 True
Checker 139901661128448 True
Thread-test2 139901671618304 True
Thread-test2: I am go dying. Please take care of yourself and drink more hot water!

------- Running threads On Pid: 6362 -------
MainThread 139901706389248 True
Thread-test1 139901682108160 True
Checker 139901661128448 True
Thread-test2 139901671618304 True
Thread-test2: I am go dying. Please take care of yourself and drink more hot water!

pid: 6362, tid: 139901682108160, tname: Thread-test1
------- Running threads On Pid: 6362 -------
MainThread 139901706389248 True
Thread-test1 139901682108160 True
Checker 139901661128448 True
// Thread-test2 已经不在了

一餐操作下來,雖然我們這樣對待Thread-test2,但它還是關心著我們:多喝熱水

PS: 熱水雖好,八杯足矣,請勿貪杯哦。

書回正傳,上述的方法是極為粗暴的,為什麼這麼說呢?

因為它的原理是:利用Python 內建的API,觸發指定執行緒的異常,讓其可以自動退出;

Python執行緒中定位與銷毀的詳細介紹(附範例)

萬不得已真不要用這種方法,有一定機率觸發不可描述的問題。切記!別問我為什麼會知道...

為什麼停止執行緒這麼難

多執行緒本身設計就是在進程下的協作並發,是調度的最小單元,執行緒間分食著進程的資源,所以會有許多鎖定機制和狀態控制。

如果使用強製手段幹掉線程,那麼很大幾率就會出現意想不到的bug。 而且最重要的鎖定資源釋放可能也會出現意想不到問題。

我們甚至無法透過訊號殺死進程那樣直接殺線程,因為 kill 只有對付程序才能達到我們的預期,而對付線程明顯不可以,不管殺哪個線程,整個行程都會退出!

而因為有 GIL,使得許多童鞋都覺得 Python 的線程是Python 自行實現出來的,並非實際存在,Python 應該可以直接銷毀吧?

然而事實上 Python 的線程都是貨真價實的線程!

什麼意思呢? Python 的執行緒是作業系統透過 pthread 建立的原生執行緒。 Python  只是透過 GIL 來約束這些線程,來決定什麼時候開始調度,比方說運行了多少個指令就交出 GIL,至於誰奪得花魁,得聽操作系統的。

如果是單純的線程,其實係統是有辦法終止的,例如: pthread_exit,pthread_kill  或pthread_cancel,  詳情可看: https://www.cnblogs.com/Creat...

可惜的是: Python 層面並沒有這些方法的封裝!我的天,好氣!可能人家覺得,線程就該溫柔對待吧。

如何溫柔退出線程

想要溫柔退出線程,其實差不多就是一句廢話了~

要么運行完退出,要么設置標誌位,時常檢查標記位,該退出的就退出咯。

擴充功能

《如何正確的終止正在運行的子執行緒》:https://www.cnblogs.com/Creat...
《不要粗暴的銷毀python執行緒》 :http://xiaorui.cc/2017/02/22/...

#歡迎各位大神指點交流, QQ討論群: 258498217
轉載請註明來源: https://segmentfault.com/a/11...







######################                                            上##############################################################

##                                                                                                                                               

  •                                                                   
  • #

    Python:執行緒之定位與銷毀
  • Python執行緒中定位與銷毀的詳細介紹(附範例)

  • #c

##linux

############################linux######################## ##########                                                                                 python############             266 次閱讀                                                 ·                                                 時所學。                                                                                        #################



                           8#                        

##                        

#                        #                        

#                        #                        #                    

背景

##開工前我覺得有什麼不太對勁,感覺要背鍋。這可不,上班第三天就捅鍋了。

我們有個了不起的後台程序,可以動態載入模組,並以執行緒方式運行,透過這種形式實現外掛程式的功能。而模組更新時候,後台程式本身不會退出,只會將模組對應的執行緒關閉、更新程式碼再啟動,6 得不行。

於是乎我就寫了個模組準備大展身手,結果忘記寫退出函數了,導致每次更新模組都新創建一個線程,除非重啟那個程序,否則那些線程就一直苟活著。

這可不行啊,得想個辦法清理呀,要不然怕是要炸了。

那麼怎麼清理呢?我能想到的就是兩步走:

找出需要清理的線程號tid;

銷毀它們;

找出線程ID

和平時的故障排查相似,先透過ps 指令看看目標行程的執行緒情況,因為已經是setName 設定過執行緒名,所以正常來說應該是看到對應的線程的。直接用下面程式​​碼來模擬這個執行緒:

Python 版本的多執行緒

#coding: utf8
import threading
import os
import time

def tt():
    info = threading.currentThread()
    while True:
        print 'pid: ', os.getpid()
        print info.name, info.ident
        time.sleep(3)

t1 = threading.Thread(target=tt)
t1.setName('OOOOOPPPPP')
t1.setDaemon(True)
t1.start()

t2 = threading.Thread(target=tt)
t2.setName('EEEEEEEEE')
t2.setDaemon(True)
t2.start()


t1.join()
t2.join()
#輸出:
root@10-46-33-56:~# python t.py
pid:  5613
OOOOOPPPPP 139693508122368
pid:  5613
EEEEEEEEE 139693497632512
...
可以看到在Python 裡面輸出的執行緒名稱就是我們設定的那樣,然而Ps 的結果卻是令我懷疑人生:
root@10-46-33-56:~# ps -Tp 5613
  PID  SPID TTY          TIME CMD
 5613  5613 pts/2    00:00:00 python
 5613  5614 pts/2    00:00:00 python
 5613  5615 pts/2    00:00:00 python
正常來說不該是這樣呀,我有點迷了,難道我一直都是記錯了?用別的語言版本的多執行緒來測試下:C 版本的多執行緒

#include<stdio.h>
#include<sys>
#include<sys>
#include<pthread.h>

void *test(void *name)
{    
    pid_t pid, tid;
    pid = getpid();
    tid = syscall(__NR_gettid);
    char *tname = (char *)name;
    
    // 设置线程名字
    prctl(PR_SET_NAME, tname);
    
    while(1)
    {
        printf("pid: %d, thread_id: %u, t_name: %s\n", pid, tid, tname);
        sleep(3);
    }
}

int main()
{
    pthread_t t1, t2;
    void *ret;
    pthread_create(&t1, NULL, test,  (void *)"Love_test_1");
    pthread_create(&t2, NULL, test,  (void *)"Love_test_2");
    pthread_join(t1, &ret);
    pthread_join(t2, &ret);
}</pthread.h></sys></sys></stdio.h>

輸出:

root@10-46-33-56:~# gcc t.c -lpthread && ./a.out
pid: 5575, thread_id: 5577, t_name: Love_test_2
pid: 5575, thread_id: 5576, t_name: Love_test_1
pid: 5575, thread_id: 5577, t_name: Love_test_2
pid: 5575, thread_id: 5576, t_name: Love_test_1
...
用PS 指令再次驗證:

root@10-46-33-56:~# ps -Tp 5575
  PID  SPID TTY          TIME CMD
 5575  5575 pts/2    00:00:00 a.out
 5575  5576 pts/2    00:00:00 Love_test_1
 5575  5577 pts/2    00:00:00 Love_test_2
這個才是正確嘛,線程名確實是可以透過Ps 看出來的嘛! 不過為啥 Python 那個看不到呢?既然是透過

setName

設定線程名的,那就看看定義咯:

[threading.py]
class Thread(_Verbose):
    ...
    @property
    def name(self):
        """A string used for identification purposes only.

        It has no semantics. Multiple threads may be given the same name. The
        initial name is set by the constructor.

        """
        assert self.__initialized, "Thread.__init__() not called"
        return self.__name

    @name.setter
    def name(self, name):
        assert self.__initialized, "Thread.__init__() not called"
        self.__name = str(name)
        
    def setName(self, name):
        self.name = name
    ...
看到這裡其實只是在

Thread 物件的屬性設定了而已,並沒有動到根本,那肯定就是看不到咯~這樣看起來,我們已經沒辦法透過ps

/proc/

這類手段在外部搜尋python 線程名了,所以我們只能在Python 內部來解決。 ######於是問題就變成了,怎麼能在 Python 內部拿到所有正在執行的執行緒呢? #########threading.enumerate###  可以完美解決這個問題! Why?######Because 在下面這個函數的 doc 裡面說得很清楚了,傳回所有活躍的###執行緒物件###,不包括終止和未啟動的。 ###
[threading.py]

def enumerate():
    """Return a list of all Thread objects currently alive.

    The list includes daemonic threads, dummy thread objects created by
    current_thread(), and the main thread. It excludes terminated threads and
    threads that have not yet been started.

    """
    with _active_limbo_lock:
        return _active.values() + _limbo.values()
###因為拿到的是 Thread 的對象,所以我們透過這個能到該線程相關的資訊! ######請看完整程式碼範例:###
#coding: utf8

import threading
import os
import time


def get_thread():
    pid = os.getpid()
    while True:
        ts = threading.enumerate()
        print '------- Running threads On Pid: %d -------' % pid
        for t in ts:
            print t.name, t.ident
        print
        time.sleep(1)
        
def tt():
    info = threading.currentThread()
    pid = os.getpid()
    while True:
        print 'pid: {}, tid: {}, tname: {}'.format(pid, info.name, info.ident)
        time.sleep(3)
        return

t1 = threading.Thread(target=tt)
t1.setName('Thread-test1')
t1.setDaemon(True)
t1.start()

t2 = threading.Thread(target=tt)
t2.setName('Thread-test2')
t2.setDaemon(True)
t2.start()

t3 = threading.Thread(target=get_thread)
t3.setName('Checker')
t3.setDaemon(True)
t3.start()

t1.join()
t2.join()
t3.join()
###輸出:###
root@10-46-33-56:~# python t_show.py
pid: 6258, tid: Thread-test1, tname: 139907597162240
pid: 6258, tid: Thread-test2, tname: 139907586672384

------- Running threads On Pid: 6258 -------
MainThread 139907616806656
Thread-test1 139907597162240
Checker 139907576182528
Thread-test2 139907586672384

------- Running threads On Pid: 6258 -------
MainThread 139907616806656
Thread-test1 139907597162240
Checker 139907576182528
Thread-test2 139907586672384

------- Running threads On Pid: 6258 -------
MainThread 139907616806656
Thread-test1 139907597162240
Checker 139907576182528
Thread-test2 139907586672384

------- Running threads On Pid: 6258 -------
MainThread 139907616806656
Checker 139907576182528
...
###程式碼看起來有點長,但是邏輯相當簡單,###Thread-test1### 和# ##Thread-test2### 都是印出目前的pid、執行緒id 和執行緒名字,然後3s 後退出,這個是想模擬執行緒正常退出。 ######而 ###Checker### 執行緒則是每秒透過 ###threading.enumerate### 輸出目前行程內所有活躍的執行緒。 ######可以明顯看到一開始是可以看到###Thread-test1### 和###Thread-test2###的訊息,當它兩個退出之後就只剩下### MainThread### 和###Checker### 本身而已了。 ######銷毀指定執行緒######既然能拿到名字和執行緒 id,那我們也就能幹掉指定的執行緒了! ######假設現在###Thread-test2### 已經黑化,發瘋了,我們需要阻止它,那我們就可以透過這種方式解決了:######在上面的程式碼基礎上,增加和補上下列程式碼:###
def _async_raise(tid, exctype):
    """raises the exception, performs cleanup if needed"""
    tid = ctypes.c_long(tid)
    if not inspect.isclass(exctype):
        exctype = type(exctype)
    res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))
    if res == 0:
        raise ValueError("invalid thread id")
    elif res != 1:
        ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)
        raise SystemError("PyThreadState_SetAsyncExc failed")

def stop_thread(thread):
    _async_raise(thread.ident, SystemExit)

def get_thread():
    pid = os.getpid()
    while True:
        ts = threading.enumerate()
        print '------- Running threads On Pid: %d -------' % pid
        for t in ts:
            print t.name, t.ident, t.is_alive()
            if t.name == 'Thread-test2':
                print 'I am go dying! Please take care of yourself and drink more hot water!'
                stop_thread(t)
        print
        time.sleep(1)
###輸出###
root@10-46-33-56:~# python t_show.py
pid: 6362, tid: 139901682108160, tname: Thread-test1
pid: 6362, tid: 139901671618304, tname: Thread-test2
------- Running threads On Pid: 6362 -------
MainThread 139901706389248 True
Thread-test1 139901682108160 True
Checker 139901661128448 True
Thread-test2 139901671618304 True
Thread-test2: I am go dying. Please take care of yourself and drink more hot water!

------- Running threads On Pid: 6362 -------
MainThread 139901706389248 True
Thread-test1 139901682108160 True
Checker 139901661128448 True
Thread-test2 139901671618304 True
Thread-test2: I am go dying. Please take care of yourself and drink more hot water!

pid: 6362, tid: 139901682108160, tname: Thread-test1
------- Running threads On Pid: 6362 -------
MainThread 139901706389248 True
Thread-test1 139901682108160 True
Checker 139901661128448 True
// Thread-test2 已经不在了
###一餐操作下來,雖然我們這樣對待###Thread-test2###,但它還是關心著我們:###多喝熱水###,######PS: 熱水雖好,八杯足矣,請勿貪杯哦。 ###

書回正傳,上述的方法是極為粗暴的,為什麼這麼說呢?

因為它的原理是:利用Python 內建的API,觸發指定執行緒的異常,讓其可以自動退出;

Python執行緒中定位與銷毀的詳細介紹(附範例)

萬不得已真不要用這種方法,有一定機率觸發不可描述的問題。切記!別問我為什麼會知道...

為什麼停止執行緒這麼難

多執行緒本身設計就是在進程下的協作並發,是調度的最小單元,執行緒間分食著進程的資源,所以會有許多鎖定機制和狀態控制。

如果使用強製手段幹掉線程,那麼很大幾率就會出現意想不到的bug。 而且最重要的鎖定資源釋放可能也會出現意想不到問題。

我們甚至無法透過訊號殺死進程那樣直接殺線程,因為 kill 只有對付程序才能達到我們的預期,而對付線程明顯不可以,不管殺哪個線程,整個進程都會退出!

而因為有 GIL,使得許多童鞋都覺得 Python 的線程是Python 自行實現出來的,並非實際存在,Python 應該可以直接銷毀吧?

然而事實上 Python 的線程都是貨真價實的線程!

什麼意思呢? Python 的執行緒是作業系統透過 pthread 建立的原生執行緒。 Python  只是透過 GIL 來約束這些線程,來決定什麼時候開始調度,比方說運行了多少個指令就交出 GIL,至於誰奪得花魁,得聽操作系統的。

如果是單純的線程,其實係統是有辦法終止的,例如: pthread_exit,pthread_kill  或pthread_cancel,  詳情可看: https://www.cnblogs.com/Creat...

可惜的是: Python 層面並沒有這些方法的封裝!我的天,好氣!可能人家覺得,線程就該溫柔對待吧。

如何溫柔退出線程

想要溫柔退出線程,其實差不多就是一句廢話了~

要么運行完退出,要么設置標誌位,時常檢查標記位,該退出的就退出咯。

擴充

《如何正確的終止正在運行的子執行緒》:https://www.cnblogs.com/Creat...
《不要粗暴的銷毀python執行緒》 :http://xiaorui.cc/2017/02/22/...

#歡迎各位大神指點交流, QQ討論群: 258498217
轉載請註明來源: https://segmentfault.com/a/11...

  • #保留所有權利


回報






如果你覺得我的文章對你有用,請隨意讚賞


你可能感興趣的



2 評論

                                                                       時間排序


           

##############################################################################################################################                                            ######################水平))                    ######                    ####  ‧  1 天前###                ################若是我可能kill -9了,寧可錯殺一千,不可放過一個,蛤蛤###

                       #                                                #                    #                     回覆                                    


#                                #                                    #                                        0                                             #                                #                                                        



##啊~ -9 流程裡一樣全死了~

##########啊~#########>

                                                                                                                                                                                                                  #                                    #                                         —                                                                                    上Python執行緒中定位與銷毀的詳細介紹(附範例)##1                                                                                

                                                

                                       

 ‧  1 天前中上

                                               

新增回覆

載入中...

#顯示更多評論

##### #######

以上是Python執行緒中定位與銷毀的詳細介紹(附範例)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文轉載於:segmentfault。如有侵權,請聯絡admin@php.cn刪除
Python中的合併列表:選擇正確的方法Python中的合併列表:選擇正確的方法May 14, 2025 am 12:11 AM

Tomergelistsinpython,YouCanusethe操作員,estextMethod,ListComprehension,Oritertools

如何在Python 3中加入兩個列表?如何在Python 3中加入兩個列表?May 14, 2025 am 12:09 AM

在Python3中,可以通過多種方法連接兩個列表:1)使用 運算符,適用於小列表,但對大列表效率低;2)使用extend方法,適用於大列表,內存效率高,但會修改原列表;3)使用*運算符,適用於合併多個列表,不修改原列表;4)使用itertools.chain,適用於大數據集,內存效率高。

Python串聯列表字符串Python串聯列表字符串May 14, 2025 am 12:08 AM

使用join()方法是Python中從列表連接字符串最有效的方法。 1)使用join()方法高效且易讀。 2)循環使用 運算符對大列表效率低。 3)列表推導式與join()結合適用於需要轉換的場景。 4)reduce()方法適用於其他類型歸約,但對字符串連接效率低。完整句子結束。

Python執行,那是什麼?Python執行,那是什麼?May 14, 2025 am 12:06 AM

pythonexecutionistheprocessoftransformingpypythoncodeintoExecutablestructions.1)InternterPreterReadSthecode,ConvertingTingitIntObyTecode,whepythonvirtualmachine(pvm)theglobalinterpreterpreterpreterpreterlock(gil)the thepythonvirtualmachine(pvm)

Python:關鍵功能是什麼Python:關鍵功能是什麼May 14, 2025 am 12:02 AM

Python的關鍵特性包括:1.語法簡潔易懂,適合初學者;2.動態類型系統,提高開發速度;3.豐富的標準庫,支持多種任務;4.強大的社區和生態系統,提供廣泛支持;5.解釋性,適合腳本和快速原型開發;6.多範式支持,適用於各種編程風格。

Python:編譯器還是解釋器?Python:編譯器還是解釋器?May 13, 2025 am 12:10 AM

Python是解釋型語言,但也包含編譯過程。 1)Python代碼先編譯成字節碼。 2)字節碼由Python虛擬機解釋執行。 3)這種混合機制使Python既靈活又高效,但執行速度不如完全編譯型語言。

python用於循環與循環時:何時使用哪個?python用於循環與循環時:何時使用哪個?May 13, 2025 am 12:07 AM

UseeAforloopWheniteratingOveraseQuenceOrforAspecificnumberoftimes; useAwhiLeLoopWhenconTinuingUntilAcIntiment.forloopsareIdealForkNownsences,而WhileLeleLeleLeleLeleLoopSituationSituationsItuationsItuationSuationSituationswithUndEtermentersitations。

Python循環:最常見的錯誤Python循環:最常見的錯誤May 13, 2025 am 12:07 AM

pythonloopscanleadtoerrorslikeinfiniteloops,modifyingListsDuringteritation,逐個偏置,零indexingissues,andnestedloopineflinefficiencies

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

mPDF

mPDF

mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

Atom編輯器mac版下載

Atom編輯器mac版下載

最受歡迎的的開源編輯器

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強大的PHP整合開發環境