Python語言之Python探針實現原理

2021-03-02 高教幫

 探針的實現主要涉及以下幾個知識點:

sys.meta_path

sitecustomize.py

sys.meta_path

sys.meta_path這個簡單的來說就是可以實現 import hook 的功能, 當執行 import 相關的操作時,會觸發 sys.meta_path 列表中定義的對象。關於 sys.meta_path 更詳細的資料請查閱 python 文檔中 sys.meta_path 相關內容以及 PEP 0302 。

sys.meta_path 中的對象需要實現一個 find_module 方法, 這個 find_module 方法返回 None 或一個實現了 load_module 方法的對象 (代碼可以從 github 上下載 part1) :

import sysclass 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 syssys.meta_path.insert(0, MetaPathFinder())if __name__ == '__main__':    import http    print(http)    print(http.version_info)

load_module 方法返回一個 module 對象,這個對象就是 import 的 module 對象了。比如我上面那樣就把 http 替換為 sys 這個 module 了。

$ python meta_path1.pyfind_module httpload_module http<module 'sys' (built-in)>sys.version_info(major=3, minor=5, micro=1, releaselevel='final', serial=0)

通過 sys.meta_path 我們就可以實現 import hook 的功能:當 import 預定的 module 時,對這個 module 裡的對象來個狸貓換太子, 從而實現獲取函數或方法的執行時間等探測信息。

上面說到了狸貓換太子,那麼怎麼對一個對象進行狸貓換太子的操作呢?對於函數對象,我們可以使用裝飾器的方式來替換函數對象(代碼可以從 github 上下載 part2) :

import functoolsimport timedef 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 wrapperdef sleep(n):    time.sleep(n)    return nif __name__ == '__main__':func = func_wrapper(sleep)    print(func(3))

我們的 import hook 是 hook.py:

import functoolsimport importlibimport sysimport 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 modulesys.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

實現一個agent:

import osimport syscurrent_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()

相關焦點

  • Python 探針實現原理
    關於 Python 的導入機制,我以前寫過一篇文章,非常詳細,感興趣的可以點擊這個連結進行查看:[深入探討 Python 的 import 機制:實現遠程導入模塊]另外,今天再給你推薦這篇文章,同樣是介紹 Python 的導入機制,和上面的文章一起食用更佳。本文呢,將簡單講述一下 Python 探針的實現原理。
  • 《小灰教你零基礎學python》-Python入門語言
    程式語言有很多,咱們就學簡單強大的python即可。Python目前是分成2個大版本,python2 和python3,python是完全免費的,所以不用擔心版權問題,因為python2已經廢棄,所以咱們這套課程完全基於python3。
  • python初學者必看的學習路線 Python是近幾年比較火的程式語言
    Python是近幾年比較火的程式語言之一,因為人工智慧的火爆,讓很多人都想從事python開發。很多零基礎學員在學習python的時候都會走一些彎路,下面小編就為大家分享python學習路線圖,幫助零基礎學員在學習的時候少走彎路。 很多人都在問Python學習步驟應該如何安排?
  • 數據分析之python語言概述
    作者看著網上各種數據分析的知識泛濫, 但是沒有什麼體系,初學者不知道學哪些, 不知道學多少, 不知道學多深, 單純一個python語言, 數據分析會用到那種程度, 不可能說像開發那樣去學, numpy如果不是做算法工程師用到的知識並不多, pandas知識雜亂無章, 哪些才是最常用的功能等等, 作者不忍眾生皆苦, 決定寫一套python數據分析的全套教程, 目前已完成一部分課件的製作
  • Python日課-2.5-python語言的不同實現
    Python 日課 2021-01-14:Python語言的不同實現。各位同學,今天來說說Python語言的種類吧。CPythonhttps://python.org我們平時說的Python,更多的是指(Python的C語言實現)。它的全稱是CPython。
  • rPython:在R語言中調用python命令
    經常使用Python和R語言的人都知道,如果R中有某些功能Python不容易實現時,則可以安裝加載rpy2包,從而實現在python中調用R語言命令的功能
  • 如何使用python語言代碼實現判斷是否為回文
    工具Visual Studio 2019python運行環境技術python回文回文,是按照中心對稱,從左到右或從右到左,字符串都一樣的。如果想要python語言代碼實現回文判斷,若為回文,列印回文,否則列印不是回文。
  • python語言在全球廣泛應用
    很簡單,還是不能去理解如何利用一些簡單的python語法去實現這些簡單的功能。比如說同樣是logistic回歸,這麼多基礎的框架,如果用python來實現,你還得去看一堆代碼,然後再自己手寫一遍代碼。那麼在日常的實際工作中,到底需要哪些簡單的工具和代碼來解決實際的問題呢?
  • Python遊戲編程
    為了達到這一目的,本課程應用python語言的語法知識帶領學生從無到有的開發遊戲,通過每個遊戲項目逐步應用學到的語法知識,在實際編程中加深體會。在課程設計中儘量站在初學者的角度,降低開發遊戲的難度,從而方便學生理解及掌握遊戲編程的基本原理和實現方法,逐步提高學生對編程的興趣和能力。
  • Python語言是什麼?python框架有哪些?Python基礎教程
    Python是什麼,Python可以做哪些Python是一種跨平臺的電腦程式設計語言,是一種面向對象的動態類型語言,最初被設計用於編寫自動化腳本(shell),隨著版本的不斷更新和語言新功能的添加,越來越多被用於獨立的
  • Python—程序語言入門
    所想要表達的意思——>編程軟體翻譯成二進位——>計算機接收並執行常用、最流行的幾種程序語言:C、C++、c#、Java 、VB、python3、Python可以用來做什麼   開發遊戲&軟體(遊戲後臺大多數用python編寫);   製作更高級的Flash(web flash game);   創建資料庫
  • 推薦: 一本「高顏值」的Python語言數據可視化圖書
    現在python語言越來越流行,尤其是在機器視覺、機器學習與深度學習等領域。但是數據可視化一直是其短板,特別相比較R語言而言。R語言以ggplot2包及其拓展包人性化的繪圖語法大受用戶的喜愛,特別是生物信息與醫學研究者。
  • 零基礎Python入門教程 - 第三節 搭建Python開發環境
    今天教大家搭建自己的Python開發環境,Python作為跨平臺語言,目前支持Windows、Linux、Mac/OS系統,考慮到後兩個系統使用門檻高,而大家對Windows的使用相對不是那麼陌生,所以我們就以Windows環境為例進行講解。
  • Python如何實現超長整數
    但是在用python編碼時,你不必擔心這些「瑣碎」的事情,因為python支持任意大小的整數。在C語言中,當你試圖使用內建的powl函數計算220000時,它會給出inf作為輸出。這使得python能夠表示和處理巨大地長整數。通常,在C這樣的低級語言中,整數的精度僅限於64位,但是Python實現了任意精度的整數。因為python3中所有的整數都被表示成一個大數,並且這些大數隻受主機系統可用內存的限制。解碼 ob_sizeob_size保存ob_digit中的元素數目。
  • Q-Q圖原理詳解及Python實現
    【導讀】在之前的《數據挖掘概念與技術 第2章》的文章中我們介紹了Q-Q圖的概念,並且通過調用現成的python函數, 畫出了Q-Q圖, 驗證了Q-Q圖的兩個主要作用,1. 檢驗一列數據是否符合正態分布 2. 檢驗兩列數據是否符合同一分布。
  • python與c語言的語法有哪些不一樣的
    在眾多程式語言之中,想必很多人都聽說過Python和C語言,在進行編程學習之前,大家都會問:python和c語言的區別有哪些?我該如何選擇?接下來我們來看看吧。python與C的區別如下:1、語言類型:Python是一種基於解釋器的語言,會逐行讀取代碼,將Python編譯為字節碼,由大型C程序解釋;C是一種編譯語言,完整的原始碼將直接編譯為機器代碼,由CPU直接執行。
  • Python 中 property 的實現原理及實現
    _x = valuec = C()print(c.x)  # Tomc.x = 'Tony'print(c.x)  # Tony儘管 property 的實現是 C 實現,但仍不妨礙探究它的實現原理,本文最後也會給出它的純 Python 版本的實現。
  • python教程之python數學運算
    存儲數據變量#兩個變量交換值,通過第三個參數實現print('兩個變量交換值,通過第三個參數實現'); #第一種方法是通過第三個參數實現x=5;#變量賦值y=11; #變量賦值中進行分數(fraction)運算分數運算是python中的一個模塊(module)。
  • 實用小工具(python or php實現)
    題圖:from Zoommy前兩天有個朋友說,想實現一個文本文件按照固定行數進行分割成多個文本文件,卻不知如何實現。
  • WTF Python:有趣且鮮為人知的Python特性
    這個有趣的項目意在收集 Python 中那些難以理解和反人類直覺的例子以及鮮為人知的功能特性,並嘗試討論這些現象背後真正的原理!雖然下面的有些例子並不一定會讓你覺得 WTFs,但它們依然有可能會告訴你一些你所不知道的 Python 有趣特性。我覺得這是一種學習程式語言內部原理的好辦法,而且我相信你也會從中獲得樂趣!