簡體   English   中英

如何動態加載和卸載Python模塊,反匯編和檢查它,但不執行初始化代碼或將其添加到sys.modules中?

[英]How do I load and unload a Python module dynamically, disassemble and inspect it, but not execute init code or add it to sys.modules?

我正在嘗試將Python模塊反匯編為字節碼。

我是否必須靜態或動態導入Python模塊才能拆卸或檢查它? 如果沒有,那么(Python的,可移植的)方法是什么?

我想:

  1. 在運行時將可用的Python模塊的二進制數據加載到內存中:
    1. 如果沒有它顯示為sys.modules的可用模塊。
    2. 我不想執行任何模塊的__init__代碼,或將其添加到任何名稱空間。
    3. 加載模塊應該沒有其他副作用。 就口譯員而言,它應該只是要檢查的數據塊。
  2. 拆卸或檢查模塊的類,功能或數據。
  3. 需要時卸載模塊。

我進行了搜索,發現了許多動態模塊導入方法(具有執行模塊__init__代碼或其他內聯代碼並插入sys.modules的副作用)。 但是我寧願不處理那些副作用。

這可能嗎? 如果是這樣,哪種方法最可移植/ Pythonic?

我對此進行了研究,一種可能的解決方案是使用pyclbr模塊。 它的檢查着眼於有關類和函數的基本信息,並將其加載到字典中以便於訪問。 這是一個示例運行:

>>> import pyclbr
>>> import sys
>>> info = pyclbr.readmodule_ex('inspect')
>>> info
{'formatargvalues': <pyclbr.Function object at 0x5083e28e50>, 'walktree': <pyclbr.Function object at 0x5083e28b50>, 'getinnerframes': <pyclbr.Function object at 0x5083e29050>, 'indentsize': <pyclbr.Function object at 0x5083e28710>, 'getmodulename': <pyclbr.Function object at 0x5083e28850>, 'formatannotation': <pyclbr.Function object at 0x5083e28d50>, 'ismemberdescriptor': <pyclbr.Function object at 0x5083e283d0>, 'iscode': <pyclbr.Function object at 0x5083e28550>, 'getsource': <pyclbr.Function object at 0x5083e28b10>, 'formatargspec': <pyclbr.Function object at 0x5083e28dd0>, 'getabsfile': <pyclbr.Function object at 0x5083e288d0>, 'getsourcelines': <pyclbr.Function object at 0x5083e28ad0>, '_getfullargs': <pyclbr.Function object at 0x5083e28c10>, 'isabstract': <pyclbr.Function object at 0x5083e28610>, 'isbuiltin': <pyclbr.Function object at 0x5083e28590>, 'getlineno': <pyclbr.Function object at 0x5083e28f10>, 'getcomments': <pyclbr.Function object at 0x5083e28990>, 'getgeneratorstate': <pyclbr.Function object at 0x5083e293d0>, 'getattr_static': <pyclbr.Function object at 0x5083e29390>, 'getframeinfo': <pyclbr.Function object at 0x5083e28ed0>, 'isgenerator': <pyclbr.Function object at 0x5083e28490>, '_static_getmro': <pyclbr.Function object at 0x5083e29190>, 'isframe': <pyclbr.Function object at 0x5083e28510>, 'getouterframes': <pyclbr.Function object at 0x5083e28f90>, 'getclasstree': <pyclbr.Function object at 0x5083e28b90>, 'getfile': <pyclbr.Function object at 0x5083e287d0>, '_shadowed_dict': <pyclbr.Function object at 0x5083e29310>, 'getargvalues': <pyclbr.Function object at 0x5083e28d10>, 'getmembers': <pyclbr.Function object at 0x5083e28650>, 'BlockFinder': <pyclbr.Class object at 0x5083e28a10>, 'isfunction': <pyclbr.Function object at 0x5083e28390>, 'getargspec': <pyclbr.Function object at 0x5083e28c50>, 'currentframe': <pyclbr.Function object at 0x5083e29090>, 'namedtuple': <pyclbr.Function object at 0x5083e1b150>, 'getmoduleinfo': <pyclbr.Function object at 0x5083e28810>, 'trace': <pyclbr.Function object at 0x5083e29110>, 'isclass': <pyclbr.Function object at 0x5083db8950>, '_is_type': <pyclbr.Function object at 0x5083e29290>, 'getcallargs': <pyclbr.Function object at 0x5083e28e90>, 'ismethoddescriptor': <pyclbr.Function object at 0x5083e28310>, 'isgeneratorfunction': <pyclbr.Function object at 0x5083e28450>, 'isroutine': <pyclbr.Function object at 0x5083e285d0>, 'getfullargspec': <pyclbr.Function object at 0x5083e28cd0>, 'getmro': <pyclbr.Function object at 0x5083e286d0>, 'getargs': <pyclbr.Function object at 0x5083e28bd0>, 'stack': <pyclbr.Function object at 0x5083e290d0>, 'getdoc': <pyclbr.Function object at 0x5083e28750>, 'findsource': <pyclbr.Function object at 0x5083e28950>, 'cleandoc': <pyclbr.Function object at 0x5083e28790>, '_check_class': <pyclbr.Function object at 0x5083e29250>, '_check_instance': <pyclbr.Function object at 0x5083e29210>, 'classify_class_attrs': <pyclbr.Function object at 0x5083e28690>, 'ismodule': <pyclbr.Function object at 0x5083db8910>, 'EndOfBlock': <pyclbr.Class object at 0x5083e289d0>, 'isdatadescriptor': <pyclbr.Function object at 0x5083e28350>, 'getmodule': <pyclbr.Function object at 0x5083e28910>, 'formatannotationrelativeto': <pyclbr.Function object at 0x5083e28d90>, 'getsourcefile': <pyclbr.Function object at 0x5083e28890>, 'ismethod': <pyclbr.Function object at 0x5083e282d0>, 'isgetsetdescriptor': <pyclbr.Function object at 0x5083e28410>, 'istraceback': <pyclbr.Function object at 0x5083e284d0>, 'getblock': <pyclbr.Function object at 0x5083e28a50>}
>>> sys.modules['inspect']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'inspect'

任何更高級的東西,您都必須開始研究通過ast模塊訪問抽象語法樹。

我找到了適用於Python 2.7的uncompyle2 ,它包含用於加載源文件並將其編譯為字節碼加載模塊並將其編譯為字節碼而不導入模塊的函數。

因此,至少看起來是可行的,但可能涉及在源代碼上調用compile() ,或者,如果使用pyc文件,則可能不可移植(uncompyle2僅對pyc文件支持Python 2.7。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM