Skip to content

Instantly share code, notes, and snippets.

@NEJmark
Last active October 19, 2021 09:40
Show Gist options
  • Save NEJmark/47f0361cb56fb356834e7ba893183262 to your computer and use it in GitHub Desktop.
Save NEJmark/47f0361cb56fb356834e7ba893183262 to your computer and use it in GitHub Desktop.
如何 trace python code
以 requesets 為例
>>> import requests
>>> r=requests.get('https://www.ptt.cc/bbs/movie/index.html')
>>> r.text
到底做了什麼事?
1. 對於一個 module 我們要知道我們使用的原始碼在電腦的哪個位置?
>>> import requests
>>> dir(requests)
['ConnectTimeout', 'ConnectionError', 'DependencyWarning', 'FileModeWarning', 'HTTPError', 'NullHandler', 'PreparedRequest', 'ReadTimeout', 'Request', 'RequestException', 'Response', 'Session', 'Timeout', 'TooManyRedirects', 'URLRequired', '__author__', '__build__', '__builtins__', '__cached__', '__copyright__', '__doc__', '__file__', '__license__', '__loader__', '__name__', '__package__', '__path__', '__spec__', '__title__', '__version__', '_internal_utils', 'adapters', 'api', 'auth', 'certs', 'codes', 'compat', 'cookies', 'delete', 'exceptions', 'get', 'head', 'hooks', 'logging', 'models', 'options', 'packages', 'patch', 'post', 'put', 'request', 'session', 'sessions', 'status_codes', 'structures', 'utils', 'warnings']
其中的 '__file__' 會回傳他的檔案位置
>>> requests.__file__
'C:\\Python34\\lib\\site-packages\\requests\\__init__.py'
打開這個檔案,你會發現上面 dir(requests) 的一大串,幾乎都有出現在這個檔案裡
(https://user-images.githubusercontent.com/5612753/30034012-a32bd4e4-91d9-11e7-86c9-95ffcbdae428.png)
所以 import 這個指令其實就是,把 requests 底下的 __init__.py 執行一次的結果,並且把執行後的所有變數都黏到 "requesets" 這個變數下面。
而我們要找的 requests.get 是甚麼呢? 其實就是
"from .api import request, get, head, post, patch, put, delete, options"
這行裡面的 get
.api 代表的是 "__init__.py 的目錄為基準,去找底下的 api.py"
而 "from .api import get" 則是代表從 api.py 裡面找 get 這個變數(可能是一個 function, class 或者是一個變數)
打開 api.py 會發現,原來 get 是一個 function 而且很短,才 3 行,註解都比程式碼多:
(https://user-images.githubusercontent.com/5612753/30034376-e19c959a-91db-11e7-97c6-0d6719e7e2d1.png)
所以他也只是去 call "request" 這個 function ,且第一個參數帶 'get',其他都是直接把你帶進來的參數往下傳
我們繼續跳到同檔案的 "request" 宣告的地方,一樣很短,只有三行,註解一堆:
(https://user-images.githubusercontent.com/5612753/30034415-2f879fac-91dc-11e7-9627-493d7ca10943.png)
看到那個 with sessions.Session() as session: 的東西, 叫做 Context Manager,他等意於:
session = sessions.Session()
session = session.__enter__()
try:
return session.request(method=method, url=url, **kwargs)
finally:
session.__exit__()
所以這邊其實就已經 new 出一個新的 session.py 的 Session class 的物件了,至於 session.py 裡面的 Session calss 就不在細說(因為很細又很多,我也沒很熟),你有興趣花時間看應該就比我還懂了
@NEJmark
Copy link
Author

NEJmark commented Sep 4, 2017

image
image
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment