4

[转]Python 探针实现原理

 3 years ago
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=


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK