天天看點

python ctypes 多線程_python 中擷取線程id

該問題的解決主要參考了網上的幾篇文章,在此一并謝過。

1、python下使用ctypes擷取threading線程id

python的多線程坑坑不斷… …

python的threading因為封裝的太好, 很多本源的東西在threading對象裡是拿不到的.  首先需要說明的是python threading的name跟ident,這些看起來是線程名字,線程id其實隻是個辨別,注意是辨別而已.  簡單過了下threading建立對象及啟動線程的代碼,發現ident跟pstree查到的線程id是兩碼事.

該文章寫的有些亂,歡迎來噴 ! 另外文章後續不斷更新中,請到原文位址檢視更新http://xiaorui.cc/?p=3017

我在 stackoverflow 查詢到了一些關于pyhton線程id的擷取方式,但大多數人其實對線程id是不關心的,他們會利用threading給予的threading.currentThread().ident threading.currentThread().name來識别線程.  最後在查到一老外寫的使用ctypes調用系統的動态連結庫libc.so.6 來擷取線程id的方法, 當然事實證明是有效果的.

ctypes是Python的一個外部庫,提供和C語言相容的資料類型,可以很友善地調用C DLL中的函數. 我對這個ctypes了解也不深入,在以前的項目中用過,表示有些粗暴.

廢話不多說, 直接上python ctypes樣例,關于這186,224,178不知道啥意思.

1

2

3importctypes

foridin[186,224,178]:

tid=ctypes.CDLL('libc.so.6').syscall(id)#syscall系統調用

下面是python threading擷取線程id的執行個體代碼:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33#xiaorui.cc

#coding:utf-8

importos

importthreading

importctypes

importtime

importrequests

defpthread_level1(i):

print"workor id :%s"%i

#擷取threading對象的辨別ident

printthreading.currentThread()

printthreading.currentThread().ident

print"threaing id: ",ctypes.CDLL('libc.so.6').syscall(186)

d=requests.get("http://www.google.com")

time.sleep(100)

return

if__name__=="__main__":

l=[]

foriinxrange(5):

t=threading.Thread(target=pthread_level1,args=(i,))

l.append(t)

foriinl:

i.start()

#檢視程序跟線程的關系

os.system("pstree -p "+str(os.getpid()))

foriinl:

i.join()

print"Sub-process done."

這是上面py代碼運作後的結果,  跟我們預期的效果一緻.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27[[email protected]:~]$pythona.py

workorid:0

workorid:1

140665607177984

140665596688128workorid:2

threaingid:24828

140665586198272

threaingid:24829

threaingid:workorid:3

140665575708416

threaingid:24830

24827

workorid:4

140665565218560

threaingid:24831

python(24826)─┬─pstree(24832)

├─{python}(24827)

├─{python}(24828)

├─{python}(24829)

├─{python}(24830)

└─{python}(24831)

可以另起一個終端使用pstree -p pid看看是否正确.

1

2

3

4

5

6[[email protected]:~]$pstree-p24826

python(24826)─┬─{python}(24827)

├─{python}(24828)

├─{python}(24829)

├─{python}(24830)

└─{python}(24831)

那麼我們費盡心思取到python的線程id是為了什麼?  strace -p pid/線程 的狀态.  可以看到24831線程正在建立google.com的連接配接, 很明顯這連接配接被拒了.

1

2

3

4

5

6

7

8

9

10[[email protected]:~]$strace-p24826

Process24826attached-interrupttoquit

futex(0x1abfcd0,FUTEX_WAIT_PRIVATE,0,NULL

^C

Process24826detached

[[email protected]:~]$strace-p24828

Process24828attached-interrupttoquit

connect(8,{sa_family=AF_INET,sin_port=htons(80),sin_addr=inet_addr

("216.58.221.228")},16

END.  下次有時間在專門瞅瞅python ctypes的用法.

對Python及運維開發感興趣的朋友可以加QQ群 : 478476595 !!!

{ 2000人qq大群内有各廠大牛,常組織線上分享及沙龍,對高性能及分布式場景感興趣同學歡迎加入該QQ群 }

另外如果大家覺得文章對你有些作用!   幫忙點選廣告. 一來能刺激我寫部落格的欲望,二來好維護雲主機的費用.

如果想賞錢,可以用微信掃描下面的二維碼. 另外再次标注部落格原位址  xiaorui.cc  ……  感謝!

其中提到的老外的文章:

So I've got a multi-threaded application and suddenly I notice there's one thread running away and using all CPU. Not good, probably a loop gone wrong. But where? One way to find this is revert history in the VCS and keep trying it out till you find the bad commit. Another way is to find out which thread is doing this, this is of course much more fun!

Using ps -p PID -f -L you'll see the thread ID which is causing the problems. To relate this to a Python thread I subclass threading.Thread, override it's .start() method to first wrap the .run() method so that you can log the thread ID before calling the original .run(). Since I was already doing all of this apart from the logging of the thread ID this was less work then it sounds. But the hard part is finding the thread ID.

Python knows of a getid(2). But this must be called using a system call with the constant name SYS_gettid. Because it's hard to use constants in ctypes (at least I don't know how to do this), and this is not portable anyway, I used this trivial C program to find out the constant value:#include

#include

int main(void)

{

printf("%d\n", SYS_gettid);

return 0;

}

In my case the constant to use is 186. Now all that is left is using ctypes to do the system call:import ctypes

SYS_gettid = 186

libc = ctypes.cdll.LoadLibrary('libc.so.6')

tid = libc.syscall(SYS_gettid)

That's it! Now you have the matching thread ID!

Going back to the original problem you can now associate this thread ID with the thread name and you should be able to find the problematic thread.

對于‘libc.so.6'的使用可以是直接調用或是先載入(Loadlibrary)都行。

2、采用ubuntu系統時可能會碰到libc.so.6位置的問題,即無法導入子產品,或無法找到該動态庫時解決方法:

在Ubuntu 14.04LTS用指令:/lib/libc.so.6時,提示” /lib/libc.so.6: not found“,其實這個庫是存在的,隻是地方換了,在"/lib/i386-linux-gnu/"下面,我們隻需建立一個連結即可。

使用下面的指令:

For 64 bit:

sudo ln -s /lib64/x86_64-linux-gnu/libc-2.13.so /lib64/libc.so.6

For 32 bit:

sudo ln -s /lib/i386-linux-gnu/libc-2.13.so /lib/libc.so.6

http://xiaorui.cc/2016/03/21/python%E4%B8%8B%E4%BD%BF%E7%94%A8ctypes%E8%8E%B7%E5%8F%96threading%E7%BA%BF%E7%A8%8Bid/

http://blog.51cto.com/happyliu/1731402