[转]Python 探针实现原理
source link: https://www.hongweipeng.com/index.php/archives/2016/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
jJri9T8/oPDiw9Yhx4ROnAXe+iNYYa5uFwwm2a1asR0OD6i+XbxNXgVwlyYSEU5V1iEnWnRT7E2hqvepQX+5eq3P2o7+dBuvn+XkDsFOABmQiTwTNI9jdiDs6BTGp4CRUYUS9RIfmvpPj2A/ST3YyzSe6oYryZm6UJUg+QL0t1g=
L2Zfyfv8SOXurGGNYPSvviK2cwCka7a92NWj/GPVOE7YKPJFzHk637S+er8RH/aurrto+WWYQRzbG/puH6n5dIp6GfqcH0VHM97/P0QcST5XqaI8U8fviCe4Kki+GSaISSyKBA2jDkxPQR/oyfbvzk85Kqu9QbBVkgPJfSrypw+WEQzFYbztH3/1SxBCQoClkEIAGQTFRc2ZrSBM6mgok96AGc4tzHDiAbSOk5X9F/OQOdwjtYkaAMay/nMdih/n
0K5psJ2WH9Ss3tlgPuW79JcZ50gHjTmdx080tbLqvxal0HzqdPF94xFag4wPcN3oduCBj+WfNaPn57pX6nPQ4Q==
- sys.meta_path
- sitecustomize.py
sys.meta_path
Tcbh8LiEZEV8Lt7rzDfpiXo0NGlZI4jJz2Wf6cNqDWVPuIXOGXC7RjZlNd2/zZwLElifh0D6Nfku4Dkm5KCbpBJc9PEnf3dCjHkss1+o4/yB9fBQiagJOsb0O8x3g8iwu4ADObE6OaVMaT+jgruKxzocJ4GT3zVfvUhmHYPm153yUkXzql37C206DtQQCVGKSBGEml+zGkcyma0ywpdoAz23WLHIDoe00Dlr5lSMAdoSAnWT/FUNxFS7C3le7cQ4qUc67TMJ5xZqsSmiQ4iSyAr/pyv4Zj5fcnucK3YsdquuWLaX6M6Jd5HryZj/1FQQuLV1VQWKPpmPGkahuax6K/B9jSt7siRVaBEPXDIF7pMS4Y43W/bI4r5RaDoW7YCApecp6sWk7bCrnavjRQr58kfTmIYqdTvzmV0+N+tDSO19ljq2gHuZg17vQxi/XxqxLIU6BFXEtr301ZhZO9ocQxnEpC49TT3bVwnpSfPSUdqiVr8+rBOm0cfhtigAYPTWuSWs8808IQaEigSIdExgPqxTIzw5cprcec11KxsMEmmCAw0FgssjH2HxGp+xPvKhbukAtN9O90+rzcj0qIqdRive28mQnKjZ5emZtMbTqzhq/rGwi5BYtSiXjbm471CO
Tcbh8LiEZEV8Lt7rzDfpiW+kUqCc2ycXE+bmUSLRwXPtqMF+dyNM0hnk7z/OH69QoyEpxlX0AavTNKzAKoKBX3f6hd4GAU7Iy2qVlhokdWawzMOCJUIyr9RPFW56mMdTnBObupH61JZFti/duJOpZZiD3j01JAGomt77rQotbQwN/uXRyjQba1cZixi2Ol1AsOxr9SvjaRy1k2xM1Bh7ocbrBzLVJ6p1WthalL93A4aAscE0IEFsuDGcBTrCF5Tt1n1C5yPwqYSjAa2+zP97+LBNkc9b6Fi15NNODZratgPBV8766SMKB2C8B6fOFL53N62o/8smWwxD/M1UFOHTdEeX08vDphq3fJwjXns/nWs=
import sys
class MetaPathFinder:
def find_module(self, fullname, path=None):
print('find_module {}'.format(fullname))
return MetaPathLoader()
class MetaPathLoader:
def load_module(self, fullname):
print('load_module {}'.format(fullname))
sys.modules[fullname] = sys
return sys
sys.meta_path.insert(0, MetaPathFinder())
if __name__ == '__main__':
import http
print(http)
print(http.version_info)
6ZneXasS4WXyeJ3swoirAxE9LR3Sf6Qh8kwKCWw64U5edZdvalNgPpkj3CwWp3uRpJsFCyJ2SJwGxbg1Dw6AYLrDF4PEyBuoc6gngL1DdHxutJrXd7vSMLCFnwB5jws2WlLx5OL638nGjTWiK78p9P4r06yKo4ETSRKjcqA/zT7AwYPyuiynC5vygjDZ/5x/EDuPr+JYZ2CTE8HtOB1/LTdVfIxzNFwyu6bnzEy5VJMCld4ZO/ayAeGS2yru/7intS8jY0+I/JFEKllD3XnKObkDx+UkJ0HUdXlrRki7nx8=
$ python meta_path1.py
find_module http
load_module http
<module 'sys' (built-in)>
sys.version_info(major=3, minor=5, micro=1, releaselevel='final', serial=0)
DCnlkZpGZMiRuuXszQ1+i32HxiC0/shDG+ucDqhs/rOFJy0GMop0Wutp9BJI6ezCaUBuuMez6pPKvJHm1zisin8KatYlrxHxs8eMbYY0CWQgD3gGK/zYa6TEXoylC0ptoG1Qvekzlrc23KzKCeN+/asc2WmmlQRPViN37ht5K2lojgtlACRXNl7E9Do9aFDUEjDC27wERHyI5Me/nXGou4NnRUojQo1OcO5Af37PoXm30OQBA/ZqUsniPcH7CTiYVn57j/LHza9vsVcII3Dx2pPPvZ6z6C4ipR9/WP878BJTWxQqycRTxCPzlP8BEzit
coPTeLICeGUK2N78kIx6CBd5XOqkqdLixElRKFMlHGxOowR0wNxf06Pf6+xyYD4sbCeC0bweiXuNYDTTTKr94gHwlCmv72iEaNsolXvJ+z3GsnePQh3rFbRh0m2aJVafsxu9hrei1VzCjuMtxy7/jY9KYVcGxjG0a83fFGLSW870ipHMKj3VcamWFt/UxhdpmxMn+89kZgq5CEJPuQJADhlKTY0tJGsax3ym+z+lmN2FSuk6QUHftP0hnvvKF5mUrwPJr2iQXs+Ceu6ItQ/oaDrZ6MxwcznjffVPW6WAbRU=
import functools
import time}
def func_wrapper(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
print('start func')
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print('spent {}s'.format(end - start))
return result
return wrapper
def sleep(n):
time.sleep(n)
return n
if __name__ == '__main__':
func = func_wrapper(sleep)
print(func(3))
7OrOBumjSaUCtZNBFyRU1A==
$ python func_wrapper.py
start func
spent 3.004966974258423s
3
fCrPR/MvfZqHPdBRVvj/UkGIhTY0QQJR+5E/B2EA6JlTVmUC6Heu8kjTGt6WgEDzSfWL83ExtXciij43azsQxa0yPg4Y/bkeDSa8IHtWSqZE6cWpgfpThvcgDxxDpiynV4Hcxk8oJYZ2himOfeCvk4n4YJ00FAPfd1ibrCRYCOto8gqI4JL2MHjwXdKSV15b
6PcCroJfn60Y1Me3PhnqX4hIy7kHnOUBZ+RUcwN3WHDxu7t6HT6WOgFidS05stAf
import time
def sleep(n):
time.sleep(n)
return n
aXcSvOcP6Rjp30QVIhovfGbA2sxkTrH8GXhvt/89gH2Jo/wnCz+xHp9PYRc2bVUg
import functools
import importlib
import sys
import time
_hook_modules = {'hello'}
class MetaPathFinder:
def find_module(self, fullname, path=None):
print('find_module {}'.format(fullname))
if fullname in _hook_modules:
return MetaPathLoader()
class MetaPathLoader:
def load_module(self, fullname):
print('load_module {}'.format(fullname))
# ``sys.modules`` 中保存的是已经导入过的 module
if fullname in sys.modules:
return sys.modules[fullname]
# 先从 sys.meta_path 中删除自定义的 finder
# 防止下面执行 import_module 的时候再次触发此 finder
# 从而出现递归调用的问题
finder = sys.meta_path.pop(0)
# 导入 module
module = importlib.import_module(fullname)
module_hook(fullname, module)
sys.meta_path.insert(0, finder)
return module
sys.meta_path.insert(0, MetaPathFinder())
def module_hook(fullname, module):
if fullname == 'hello':
module.sleep = func_wrapper(module.sleep)
def func_wrapper(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
print('start func')
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print('spent {}s'.format(end - start))
return result
return wrapper
Jqw6SbPtqE3oIMcTSCS4Ag==
>>> import hook
>>> import hello
find_module hello
load_module hello
>>>
>>> hello.sleep(3)
start func
spent 3.0029919147491455s
3
>>>
cFuFqQjyJoBE0c4n6naSagsE8IM7R/NmTyXPCx891VDK2HQsc+rjs9YTOHdtJucGXDVTn8fbQl33vYqvAVAiuPMPuzU83RvTysHnh4/SUkOmzwNgBQYH3lcydCtEq0I+xnJyYvwk9xWJxnhsPEOM8JeYFZ8LsLe6UhTMzkgdZtGnGrOpcIvD9AsAE+U2IAS2MX54h+p6dMJxhnnOGiKJB4YuAoQfUJk0zJCgVc/y6iZJ4wq8tXzPca4JLsMqVYTrCFJ0jnMtEeNKGZfyC8mjqA==
vmpIgadTr6ghHSBl/8dg65zC8+AdyGprcyUV55EFZUzv7BLRgXC4Lif+j+VF7QgtfveOo2hgOtXM4w3UUUxSJ6kPDskKO1my3Z0WlnxZBfqyjtVkCFyfquvE4mPZrI5RTT/KG36BulW9I+rvGKVIWTiee6W3Hw14t9jLtX82TIzNoFX8d1Pr7Wb4XdX7FXF+pKlmbVQ9rpZq1eQa4UbuPjC4fTbV6guyBNf4Piqn122ql32Qjz6CoHe1uPmXdr2KvqvdQi36AZNn9b1d/IgPMg==
sitecustomize.py
cVfWVYRSWIqCLnS1hPIjBcvPU8rDeoBnTARz5Sm0jIYnBaSqR3l3k9him2rmD/5tDnu/OgKuj7Z+3SgiII3s8AuqjdsKrqKrEm+lNEEJ+yL57PbIeabxxHMhHhbmJsmvSRfnl3taFe2aqR29GV7t0VX3791Hr3aeIWdy/XEtTJL/mqzpz3jWs7FPMThhZaqo7nFUu880aIHKlibcDKUok8l6OoEE3peqOVX489/bVAc=
YAUa9j6Xa/7h88738zFi7WFe62uZd7oSuuQLZXD0neS/rdZlBi2JJLkkHdmHiwX8cls/ufzTyd7l5lVnVay+YCDdp5jCLK3jwUJAFvFHuN0=
$ tree
.
├── sitecustomize.py
└── usercustomize.py
lYSzgv9aZxHhBGwvH6ea4WgEalz16qXAuNtNdExJSu8=
$ cat sitecustomize.py
print('this is sitecustomize')
q/v/yrY4xw8407c2FVHtoOXdlurDPwAAANXDV7N9bn0=
$ cat usercustomize.py
print('this is usercustomize')
4WClbYZeU83V7pb4nuYrumig7J86AzmTrAEMeZIv5QChg4BZbnORQBiaW7Vhu52C8TrauH4AuZ3aFiLqrx2QSTdoDqwiZyqpi+48epuzk7w=
$ export PYTHONPATH=.
$ python
this is sitecustomize <----
this is usercustomize <----
Python 3.5.1 (default, Dec 24 2015, 17:20:27)
[GCC 4.2.1 Compatible Apple LLVM 7.0.2 (clang-700.1.81)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>
vuemUFZbJHtGItriQqV3fweCS50qKoigVIRKYPfWgvHUDrsiX4I0xfdq4vdJcqAKW8lSJKWAIOtsTWYLYbe8/fHtMeMRhcjR1lMNeguSAWouSfeIB/oyJLCFQjhan3YVLYzYELrziKPPbzArSEXmM1q3nlt0kWuyoCHohYKabab8xZGB2vSjD5/1k/gckQntIzvgPZHc1jo7DShMTFcDig==
h1/KiQr1xi8sqIZlvZY5lQ==
$ tree
.
├── hello.py
├── hook.py
├── sitecustomize.py
lYSzgv9aZxHhBGwvH6ea4WgEalz16qXAuNtNdExJSu8=
$ cat sitecustomize.py
import hook
y8YelPkRbYdg5spvCnjHmQ==
$ export PYTHONPATH=.
$ python
find_module usercustomize
Python 3.5.1 (default, Dec 24 2015, 17:20:27)
[GCC 4.2.1 Compatible Apple LLVM 7.0.2 (clang-700.1.81)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
find_module readline
find_module atexit
find_module rlcompleter
>>>
>>> import hello
find_module hello
load_module hello
>>>
>>> hello.sleep(3)
start func
spent 3.005002021789551s
3
wduZqF+W4C/HCHqRxPEiQYRqXBgNwhgXHtVZS48Sm6W3Z/74VyONQgRyLy+eW7CuYLX2mC0E7NIX5xNcmEiaydDl0C8SLG9Fl1Y/q+nXJ7b+anesum5dUA+IhpfOWqRC8tuGx4sjwtA1S5b3q32bTBBIOxEGGwTk8uADKDeG4kIAB2VaXJwS/ZT5h83y52qM4iGVfQhIA8ho7Blb4DgfTH+jKbsXiAvmmAT1UMZQvhLClyEEvtFPQWkLatdfO8lysZ/IpxFD37j+t93LzWnfHO+e4NK3y4kPiHb4eU3nSWEIWhDvp+FPfKubHYFMv1L7zn1vSH8xfLRl6XIdmfY64hTQ3aGYqI/60BD90CLx2sMK4g+LaTc8iiKPUhCmLx8YGqvXPDgNPvZ9NhFsdPFmNyoPqO8QPPtaHNyw6fJ0RM925BC0+Ihh+pDvLM4NVGhi0WQy11+pXhnIJOI6bUzRDkkeOtxf50Irm6am8zCDDPu18+iUgTQ6mcrrmAgGG/wpKK7TqNG+THiS9E7m2qsg/w==
ycOc1MNcwhGqb1nhBLBXy9H7hJIgl4nL8Da/kN/VbEf1nYbc3cyZ1pIbpZEWNFtl8QOwoxRrIcsEwdhYng7vNKW8QT7KlT/tb08Ff87Bb1PA8ySfZItFs6L9pcvHqY0w
agent
2/7cEqcZPXuynV258hMAHgL6iuEUSZiC7jbPt5KQe79rU2RI/iSZuMsqju2jXVhM3ZAyviS3LHy3TSZHDQj7cij/+80uFJNLytVSG6rfbumNRLOh597fHCFaw5ACWY1omqfMHb/AD4Jnutv3V0pKnrMFxxFWE7ybW/hfmc6hb2lv5kxY1H//a/n05pOkf8HhW1bzrchDxH3XGnqpd5aK2i/5bF2+4cMdZA6WnTubOAJivav+DuPPVNu+Vhr26V+GUJUCDZr7Uc5B7khzSyQL/p3Z6FZxHv+E1KzcS8TMTVhJk4sYOF5jd0IiIh8YA+NyNhNoo9TpqoPL+CyTw/gk9g==
$ mkdir bootstrap
$ mv hook.py bootstrap/_hook.py
$ touch bootstrap/__init__.py
$ touch agent.py
$ tree
.
├── bootstrap
│ ├── __init__.py
│ ├── _hook.py
│ └── sitecustomize.py
├── hello.py
├── test.py
├── agent.py
hmqZG3v1RFYGhNJVM1OlgMhQkkb7rIPaaHjQsnkJ6MeNV0R0OwPmjoUc+7uRSMQ6LQ2u8AfoRlMcUnHF2O5/OQ==
$ cat bootstrap/sitecustomize.py
import _hook
//gZwFzJVPfCTeliJsX6q/Wd+X5ps1N2Db1F6fDcQjs=
import os
import sys
current_dir = os.path.dirname(os.path.realpath(__file__))
boot_dir = os.path.join(current_dir, 'bootstrap')
def main():
args = sys.argv[1:]
os.environ['PYTHONPATH'] = boot_dir
# 执行后面的 python 程序命令
# sys.executable 是 python 解释器程序的绝对路径 ``which python``
# >>> sys.executable
# '/usr/local/var/pyenv/versions/3.5.1/bin/python3.5'
os.execl(sys.executable, sys.executable, *args)
if __name__ == '__main__':
main()
2YDyWqqJxIY0lpCKoKziArmybwOCHhaLNAkx5cX2szZVxIO2VgKzSFzAyGrmEkF8
$ cat test.py
import sys
import hello
print(sys.argv)
print(hello.sleep(3))
TP+f2fNvVSuODecBKCRNQA==
$ python agent.py test.py arg1 arg2
find_module usercustomize
find_module hello
load_module hello
['test.py', 'arg1', 'arg2']
start func
spent 3.005035161972046s
3
XXc/onUi+VqcSXrMtqknTb1LsKMlGec3dUyrmeDlhzC5foZU13BABFXpX34utiWt7pkUP/ggJwgfgxVAZ7tn5C8o9UgMp6BMs+Jnz5d/mRyircVKF2rruuzz3feN9XLitIVD9rmFjtX3eVUeYfKP1EpW0U2kTItXI84vlVOh8iN+H7/8Ola3Y5ZNtgdDjYQu8957GSsBV92hKCu93+MMTd8IT97kvXvIEEyVJdMqP1rvOnL/ET0jqUtPCEjYcEE4v2yGbC9au/1IEGQwvATSYw==
mPBKzQjcINw/yRXIspEK0aDFyoe11ypZ4fl8nXi7NPDjfcVWq/OdyOX2zI2MZzld0bWypSkNHXZArlyUIibuvbaB+xsj51m41IchkofgCoZoMCGzO/R5P89LjGuAJ4S57n69GoXyLAeWj4NhbTqUjTcCsG0J0T4qMW2HcZc4028J88UmVZpv5RbuE/lnlivMAmKcuHOTImYonV1Po/LAdIR8te+oLhrwYp3JN1ofFegqLtulp3Np0wN5gm/HUAsZ0kkpqUu3hV5U6/MZXAVhxrrp+2NKsm8D37DmbH8iUiXTTDjMzVgFD5rVZSWphH+Zm6wukSjm1LZt1IsP18gQqTk0F5gVZGHeMHS8e0IRmOjh/6TNdBD8G3XIRFKnkVWa/cSNqcRzzwFp9Fen1Fp7hxgitGo4t552+VjSj9PotmIwPUQ8WVUWTgc5WHryT+QAcLpXjl9VgH40t8tSfFqAcgaDyrNYR4aME05tkrVSx5LncUNVlYZ97JSVwBxDtBgD
m2ioclOxn9He7yKKUhkdHUnEOC/kcTde+kjEw1bARMWU0Q74ietEPAQ9z0P0Md822+usrjsGvdW4zHytGOnu+H1aALepU+sRCDWilLQCuOABND46VWA6nnzeFQDh+nJXpFJ8vBsF2yTz4XwFsIbf5KenLm3FlgkiuY+7b71wHHw=
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK