pycodeobject库是一个用于解析、编辑和处理Python字节码(bytecode)的工具。
PyCodeObject is a tool for parsing and processing Python bytecode object.
详细介绍
========
字节码的结构
"""""""""""""""""""""""
众所周知, Python中的字节码(bytecode) 是一种数据类型, Python代码的编译结果就是bytecode对象。
bytecode对象可以由虚拟机加载后直接运行,而pyc文件就是bytecode在硬盘上的保存形式。
先通过一个示例, 分析什么是字节码::
.. code-block:: python
>>> import dis
>>> def f(x):print('hello',x)
>>> f.__code__
<code object f at 0x02B27498, file "<pyshell#2>", line 1>
>>> f.__code__.co_code
b't\x00d\x01|\x00\x83\x02\x01\x00d\x00S\x00'
>>> dis.dis(f)
1 0 LOAD_GLOBAL 0 (print)
2 LOAD_CONST 1 ('hello')
4 LOAD_FAST 0 (x)
6 CALL_FUNCTION 2
8 POP_TOP
10 LOAD_CONST 0 (None)
12 RETURN_VALUE
>>>
上述示例中f.__code__就是bytecode对象, f.__code__.co_code就是二进制的字节码, 通过dis模块可以反编译、分析这些二进制代码。
Python解释执行代码时, 会首先将原始的源代码翻译成bytecode形式, 再直接执行bytecode, 以提高性能。
.. image:: https://img-blog.csdnimg.cn/20210719105023666.png
:alt: 字节码结构图
(在 Python 3.8中, 增加了一个属性 `co_posonlyargcount`, 而Python 3.11的字节码有较大的改动)
详尽的说明参见Python官方文档 https://docs.python.org/zh-cn/3.7/library/dis.html 。
包装字节码
""""""""""""""""""""
在python中, bytecode对象的属性是不可修改的。如::
.. code-block:: python
>>> def f():pass
>>> f.__code__.co_code = b''
Traceback (most recent call last): ... ...
AttributeError: readonly attribute
为了使bytecode对象更易用, 本项目中的Code类, 用于包装 (wrap)字节码对象。
下面的示例是从doctest中摘取的::
.. code-block:: python
>>> def f():print("Hello")
>>> c=Code.fromfunc(f) # 或 c=Code(f.__code__)
>>> c.co_consts
(None, 'Hello')
>>> c.co_consts=(None, 'Hello World!')
>>> c.exec()
Hello World!
>>>
>>> import os,pickle
>>> temp=os.getenv('temp')
>>> with open(os.path.join(temp,"temp.pkl"),'wb') as f:
... pickle.dump(c,f)
...
>>> f=open(os.path.join(temp,"temp.pkl"),'rb')
>>> pickle.load(f).to_func()()
Hello World!
>>>
>>> c.to_pycfile(os.path.join(temp,"temppyc.pyc"))
>>> sys.path.append(temp)
>>> import temppyc
Hello World!
>>> Code.from_pycfile(os.path.join(temp,"temppyc.pyc")).exec()
Hello World!
版本 VERSION
============
1.0.5 (更新: 增加了对3.10及以上版本的支持。)
**本模块与pyobject库的关系**
pycodeobject库最初是作者单独开发的项目。后来因pyobject库的开发,pycodeobject库被整合到了pyobject.code_模块中。现今的pyobject的Code类和本模块的Code类完全相同。
作者 AUTHOR
===========
qfcy qq:3076711200 贴吧账号:qfcy\_
作者CSDN主页: https://blog.csdn.net/qfcy\_
Raw data
{
"_id": null,
"home_page": "https://github.com/qfcy/Python/blob/main/pyobject/code_.py",
"name": "pycodeobject",
"maintainer": null,
"docs_url": null,
"requires_python": null,
"maintainer_email": null,
"keywords": "python, bytecode, \u5b57\u8282\u7801, assembly, pyc, decompiling, \u53cd\u7f16\u8bd1",
"author": "qfcy qq:3076711200",
"author_email": "3076711200@qq.com",
"download_url": "https://files.pythonhosted.org/packages/2f/82/c0966747f1c8a51a046b50d9f779efa985a88a2c3673b9270b1a26502cfe/pycodeobject-1.0.5.tar.gz",
"platform": null,
"description": "pycodeobject\u5e93\u662f\u4e00\u4e2a\u7528\u4e8e\u89e3\u6790\u3001\u7f16\u8f91\u548c\u5904\u7406Python\u5b57\u8282\u7801(bytecode)\u7684\u5de5\u5177\u3002\r\n\r\nPyCodeObject is a tool for parsing and processing Python bytecode object.\r\n\r\n\u8be6\u7ec6\u4ecb\u7ecd\r\n========\r\n\r\n\u5b57\u8282\u7801\u7684\u7ed3\u6784\r\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\r\n\r\n\u4f17\u6240\u5468\u77e5, Python\u4e2d\u7684\u5b57\u8282\u7801(bytecode) \u662f\u4e00\u79cd\u6570\u636e\u7c7b\u578b, Python\u4ee3\u7801\u7684\u7f16\u8bd1\u7ed3\u679c\u5c31\u662fbytecode\u5bf9\u8c61\u3002\r\n\r\nbytecode\u5bf9\u8c61\u53ef\u4ee5\u7531\u865a\u62df\u673a\u52a0\u8f7d\u540e\u76f4\u63a5\u8fd0\u884c\uff0c\u800cpyc\u6587\u4ef6\u5c31\u662fbytecode\u5728\u786c\u76d8\u4e0a\u7684\u4fdd\u5b58\u5f62\u5f0f\u3002\r\n\u5148\u901a\u8fc7\u4e00\u4e2a\u793a\u4f8b, \u5206\u6790\u4ec0\u4e48\u662f\u5b57\u8282\u7801::\r\n\r\n.. code-block:: python\r\n\r\n >>> import dis\r\n >>> def f(x):print('hello',x)\r\n \r\n >>> f.__code__\r\n <code object f at 0x02B27498, file \"<pyshell#2>\", line 1>\r\n >>> f.__code__.co_code\r\n b't\\x00d\\x01|\\x00\\x83\\x02\\x01\\x00d\\x00S\\x00'\r\n >>> dis.dis(f)\r\n 1 0 LOAD_GLOBAL 0 (print)\r\n 2 LOAD_CONST 1 ('hello')\r\n 4 LOAD_FAST 0 (x)\r\n 6 CALL_FUNCTION 2\r\n 8 POP_TOP\r\n 10 LOAD_CONST 0 (None)\r\n 12 RETURN_VALUE\r\n >>> \r\n\r\n\u4e0a\u8ff0\u793a\u4f8b\u4e2df.__code__\u5c31\u662fbytecode\u5bf9\u8c61, f.__code__.co_code\u5c31\u662f\u4e8c\u8fdb\u5236\u7684\u5b57\u8282\u7801, \u901a\u8fc7dis\u6a21\u5757\u53ef\u4ee5\u53cd\u7f16\u8bd1\u3001\u5206\u6790\u8fd9\u4e9b\u4e8c\u8fdb\u5236\u4ee3\u7801\u3002\r\n\r\nPython\u89e3\u91ca\u6267\u884c\u4ee3\u7801\u65f6, \u4f1a\u9996\u5148\u5c06\u539f\u59cb\u7684\u6e90\u4ee3\u7801\u7ffb\u8bd1\u6210bytecode\u5f62\u5f0f, \u518d\u76f4\u63a5\u6267\u884cbytecode, \u4ee5\u63d0\u9ad8\u6027\u80fd\u3002\r\n\r\n.. image:: https://img-blog.csdnimg.cn/20210719105023666.png\r\n :alt: \u5b57\u8282\u7801\u7ed3\u6784\u56fe\r\n\r\n(\u5728 Python 3.8\u4e2d, \u589e\u52a0\u4e86\u4e00\u4e2a\u5c5e\u6027 `co_posonlyargcount`, \u800cPython 3.11\u7684\u5b57\u8282\u7801\u6709\u8f83\u5927\u7684\u6539\u52a8)\r\n\r\n\u8be6\u5c3d\u7684\u8bf4\u660e\u53c2\u89c1Python\u5b98\u65b9\u6587\u6863 https://docs.python.org/zh-cn/3.7/library/dis.html \u3002\r\n\r\n\u5305\u88c5\u5b57\u8282\u7801\r\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\r\n\r\n\u5728python\u4e2d, bytecode\u5bf9\u8c61\u7684\u5c5e\u6027\u662f\u4e0d\u53ef\u4fee\u6539\u7684\u3002\u5982::\r\n\r\n.. code-block:: python\r\n\r\n >>> def f():pass\r\n >>> f.__code__.co_code = b''\r\n Traceback (most recent call last): ... ...\r\n AttributeError: readonly attribute\r\n\r\n\u4e3a\u4e86\u4f7fbytecode\u5bf9\u8c61\u66f4\u6613\u7528, \u672c\u9879\u76ee\u4e2d\u7684Code\u7c7b, \u7528\u4e8e\u5305\u88c5 (wrap)\u5b57\u8282\u7801\u5bf9\u8c61\u3002\r\n\r\n\u4e0b\u9762\u7684\u793a\u4f8b\u662f\u4ecedoctest\u4e2d\u6458\u53d6\u7684::\r\n\r\n.. code-block:: python\r\n\r\n >>> def f():print(\"Hello\")\r\n >>> c=Code.fromfunc(f) # \u6216 c=Code(f.__code__)\r\n >>> c.co_consts\r\n (None, 'Hello')\r\n >>> c.co_consts=(None, 'Hello World!')\r\n >>> c.exec()\r\n Hello World!\r\n >>>\r\n >>> import os,pickle\r\n >>> temp=os.getenv('temp')\r\n >>> with open(os.path.join(temp,\"temp.pkl\"),'wb') as f:\r\n ... pickle.dump(c,f)\r\n ... \r\n >>> f=open(os.path.join(temp,\"temp.pkl\"),'rb')\r\n >>> pickle.load(f).to_func()()\r\n Hello World!\r\n >>> \r\n >>> c.to_pycfile(os.path.join(temp,\"temppyc.pyc\"))\r\n >>> sys.path.append(temp)\r\n >>> import temppyc\r\n Hello World!\r\n >>> Code.from_pycfile(os.path.join(temp,\"temppyc.pyc\")).exec()\r\n Hello World!\r\n\r\n\u7248\u672c VERSION\r\n============\r\n 1.0.5 (\u66f4\u65b0: \u589e\u52a0\u4e86\u5bf93.10\u53ca\u4ee5\u4e0a\u7248\u672c\u7684\u652f\u6301\u3002)\r\n\r\n\t**\u672c\u6a21\u5757\u4e0epyobject\u5e93\u7684\u5173\u7cfb**\r\n\r\n\tpycodeobject\u5e93\u6700\u521d\u662f\u4f5c\u8005\u5355\u72ec\u5f00\u53d1\u7684\u9879\u76ee\u3002\u540e\u6765\u56e0pyobject\u5e93\u7684\u5f00\u53d1\uff0cpycodeobject\u5e93\u88ab\u6574\u5408\u5230\u4e86pyobject.code_\u6a21\u5757\u4e2d\u3002\u73b0\u4eca\u7684pyobject\u7684Code\u7c7b\u548c\u672c\u6a21\u5757\u7684Code\u7c7b\u5b8c\u5168\u76f8\u540c\u3002\r\n\r\n\u4f5c\u8005 AUTHOR\r\n===========\r\n qfcy qq:3076711200 \u8d34\u5427\u8d26\u53f7:qfcy\\_\r\n\r\n \u4f5c\u8005CSDN\u4e3b\u9875: https://blog.csdn.net/qfcy\\_\r\n",
"bugtrack_url": null,
"license": null,
"summary": "\u7528\u4e8e\u89e3\u6790\u3001\u7f16\u8f91\u548c\u5904\u7406Python\u5b57\u8282\u7801(bytecode)\u7684\u5de5\u5177\u3002A tool for parsing and processing Python bytecode object.",
"version": "1.0.5",
"project_urls": {
"Homepage": "https://github.com/qfcy/Python/blob/main/pyobject/code_.py"
},
"split_keywords": [
"python",
" bytecode",
" \u5b57\u8282\u7801",
" assembly",
" pyc",
" decompiling",
" \u53cd\u7f16\u8bd1"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "2f82c0966747f1c8a51a046b50d9f779efa985a88a2c3673b9270b1a26502cfe",
"md5": "339fdebc48ac211f141a74de61675652",
"sha256": "f2105dfe9d03fc86d9f2169ca30a6e318cd2d5041020558094b778cb3f42691a"
},
"downloads": -1,
"filename": "pycodeobject-1.0.5.tar.gz",
"has_sig": false,
"md5_digest": "339fdebc48ac211f141a74de61675652",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 13267,
"upload_time": "2024-08-12T12:12:41",
"upload_time_iso_8601": "2024-08-12T12:12:41.021754Z",
"url": "https://files.pythonhosted.org/packages/2f/82/c0966747f1c8a51a046b50d9f779efa985a88a2c3673b9270b1a26502cfe/pycodeobject-1.0.5.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-08-12 12:12:41",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "qfcy",
"github_project": "Python",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "pycodeobject"
}