|
python编译相关
具体编译步骤
Python代码的编译和执行过程可以更详细地描述如下:
整个过程中,Python代码并不会直接编译成机器代码,而是先被解释器解析为字节码,然后由解释器执行字节码。这种解释型的方式使得Python具有跨平台性,因为字节码是与硬件无关的,只要有对应的解释器,Python代码就可以在不同平台上执行。。
如何生成pyc文件
- 在py程序内部
使用 Python 自带的 py_compile 模块来将 .py 文件编译成 .pyc 文件。这个模块提供了一个名为 compile 的函数,你可以使用它来编译 Python 源文件。- def greet(name):
- return f"Hello, {name}!"
- print(greet("Alice"))
复制代码 运行这段代码将会在源文件所在的目录下生成一个与源文件同名的 .pyc 文件。
compileall 模块也是用于将 Python 源文件编译成字节码文件的工具,它比 py_compile 模块更加灵活,可以批量编译目录下的所有 .py 文件。- Module(
- body=[
- FunctionDef(
- name='greet',
- args=arguments(
- //arg 表示函数的一个参数,arguments 则表示函数定义中的参数集合。
- args=[
- arg(arg='name', annotation=None)
- ],
- defaults=[],
- //defaults:这表示位置参数的默认值。它也是一个列表,但在这个例子中是空的。如果函数的某些参数有默认值,那么这里会指定这些默认值。
- kw_defaults=[],
- //kw_defaults:这表示关键字参数的默认值。与 defaults 类似,它也是一个列表。然而,在这个例子中也是空的,表示函数的关键字参数没有默认值。
- kwarg=None,
- //kwarg:这表示用于收集未明确定义的额外关键字参数的关键字参数的名称。在这个例子中,它设置为 None,表示函数不接受超出明确定义的关键字参数之外的其他关键字参数。
- kwonlyargs=[],
- //kwonlyargs:这表示仅关键字参数。关键字参数是一种只能通过关键字传递并且在参数列表中在 * 之后指定的参数。在这个例子中也是一个空列表。
- kwargannotation=None
- //kwargannotation:这表示 kwarg 的注释,如果有的话。注释是可选的元数据,可以附加到函数参数上,指示参数的预期类型或用途。在这个例子中,它设置为 None,表示未为 kwarg 指定注释。
- ),
- body=[
- Return(
- //Return 表示函数的返回语句,用于从函数中返回一个值。在这里,Return 节点表示函数的返回部分。
- value=JoinedStr(
- //value 属性指定了要返回的值。在这里,value 是一个 JoinedStr 对象,它表示一个由多个字符串拼接而成的复合字符串。JoinedStr 表示一个由多个字符串组成的复合字符串。
- values=[
- //values 属性是一个列表,包含了组成复合字符串的各个部分。在这里,复合字符串由 'Hello, '、Name 对象和 '!' 三部分组成。
- Str(s='Hello, '),
- FormattedValue(
- //FormattedValue 表示格式化值,用于在字符串中插入变量。value 属性是一个 Name 对象,表示要插入的变量名。在这里,Name(id='name', ctx=Load()) 表示要插入的变量是函数参数 name。
- value=Name(id='name', ctx=Load()),
- conversion=-1,
- format_spec=None
- ),
- Str(s='!')
- ]
- )
- )
- ],
- decorator_list=[]
- ),
- Expr(
- //Expr 表示一个表达式语句,用于执行函数调用或其他表达式。
- value=Call(
- //Call 表示函数调用表达式。func 属性是一个 Name 对象,表示要调用的函数名。在这里,Name(id='print', ctx=Load()) 表示要调用的函数是内置函数 print()。
- func=Name(id='print', ctx=Load()),
- args=[
- Call(
- func=Name(id='greet', ctx=Load()),
- //id 和 ctx 分别是 Name 对象的两个属性:id 属性:表示标识符的名称。在这里,id='print' 表示标识符的名称是 'print',即函数名或变量名为 print。ctx 属性:表示标识符的上下文(Context)。ctx 可以指定标识符在代码中的使用方式,例如加载(load)、存储(store)等。在这里,ctx=Load() 表示该标识符在这个上下文中是一个加载(load)的标识符,即在代码中引用了名为 'print' 的函数或变量。
- args=[
- Str(s='Alice')
- ],
- keywords=[]
- )
- ],
- keywords=[]
- )
- )
- ]
- )
复制代码 这将会编译指定目录下的所有 Python 源文件,并在相同目录下生成对应的 .pyc 文件。
- 使用命令行工具来编译 Python 源文件,
例如在命令行中执行以下命令:- 1. 位置参数(Positional Arguments):
- 位置参数是函数定义中的普通参数,它们按照在函数参数列表中的顺序进行传递,不需要指定参数名称。例如,在函数定义中,`def my_function(a, b):` 中的 `a` 和 `b` 就是位置参数。在调用函数时,传递的参数值会按照位置与位置参数一一对应。
- 2. 默认值(Default Values):
- 默认值是在函数定义中为参数提供的初始值。如果在函数调用时没有提供对应参数的值,那么参数将使用默认值。默认值允许函数在某些情况下以可选方式接受参数。例如,在函数定义中,`def greet(name="Guest"):`, 这里的 `name` 参数有一个默认值 `"Guest"`。如果调用 `greet()` 时没有传递参数,它将使用默认值 `"Guest"`。
- 3. 仅关键字参数(Keyword-Only Arguments):
- 仅关键字参数是只能通过关键字传递的参数,这些参数出现在函数定义中的 `*` 符号之后。这意味着在函数调用时必须使用参数名称来传递这些参数值。这种类型的参数可以增加函数的灵活性和可读性。例如,在函数定义中,`def greet(name, *, prefix="Hello"):` 中的 `prefix` 参数就是一个仅关键字参数。这意味着在调用 `greet()` 时必须通过关键字指定 `prefix` 参数的值,例如 `greet("Alice", prefix="Hi")`。
- 4. 注释(Annotations):
- 注释是Python中的一种元数据,用于为函数参数或变量提供类型信息或其他说明。注释不会影响代码的运行,但可以提供更多的信息,帮助理解代码的含义和用法。例如,在函数定义中,`def greet(name: str):`, 这里的 `str` 就是参数 `name` 的注释,指示其应该是一个字符串类型。注释可以在函数定义时使用冒号(`:`)后面的形式指定。在实际运行中,这些注释并不会被Python解释器使用,但可以被其他工具或IDE用来进行类型检查或提供代码提示。
复制代码 这将在同一目录下生成一个名为 example.pyc 的文件。
pyo
.pyo 文件与 .pyc 文件相似,只是在优化模式下生成,并且可能会删除一些调试信息和注释。
在 Python 3.x 中,默认情况下,当你使用优化标志(-O 或 -OO)运行 Python 解释器时,生成的字节码文件将使用 .pyo 扩展名而不是 .pyc。这些优化标志会启用优化编译器标志,从而在生成的字节码中删除一些调试信息或注释,以减小字节码文件的大小并提高执行效率。
- O:启用优化编译,将会删除 assert 语句。
- OO:启用更严格的优化,将会删除 assert 语句以及文档字符串(docstrings)。
生成的 .pyo 文件可以被 Python 解释器加载和执行,与 .pyc 文件的使用方式相同。不过需要注意的是,.pyo 文件并不会自动替换 .pyc 文件,而是作为 .pyc 文件的一个替代品。因此,如果你在优化模式下运行了一个 Python 脚本,它会生成一个 .pyo 文件,但如果以普通模式再次运行同一个脚本,它还是会生成 .pyc 文件。
拿到pyc文件后反编译回py文件
利用uncompyle6 这个Python 反编译工具它用于将 Python 字节码文件(.pyc 或 .pyo 文件)反编译回等效的 Python 源代码。
直接在命令行中安装 uncompyle6 就可以用了- import py_compile
- # 指定要编译的 Python 源文件路径
- source_file = 'example.py'
- # 编译 Python 源文件,并生成对应的 .pyc 文件
- py_compile.compile(source_file)
复制代码 安装完成后,就可以使用以下命令将字节码文件反编译为 Python 源代码:- import compileall
- # 指定要编译的目录路径
- directory = '/path/to/directory'
- # 编译目录下的所有 Python 源文件,并生成对应的 .pyc 文件
- compileall.compile_dir(directory)
复制代码 或者,如果是一个 .pyo 文件,也可以用相同的方式进行反编译:- python -m py_compile example.py
复制代码 解释和编译
编译器:先整体编译再执行
解释器:边解释边执行
优缺点:
编译方式:运行速度快,但是任何的改动都要整体重新编译。可以脱离编译环境运行。C语言
解释方式:运行速度慢,但是部分的改动不需要整体重新编译。不可以脱离解释器环境运行。python
说是python慢,但是也有优化速度的方式,也就是生成pyc文件的方式。参考了JAVA的字节码做法,但并不完全相同。其作用就是减少重复的解释工作。
Python 有几种不同的解释器
最常见的包括:
- CPython:CPython 是 Python 的官方解释器,它是使用 C 语言实现的。CPython 是最常用的 Python 解释器,它执行 Python 代码,并提供了许多标准库和扩展模块。
- Jython:Jython 是一个在 Java 平台上运行的 Python 解释器。它将 Python 代码编译成 Java 字节码,然后在 Java 虚拟机(JVM)上执行。Jython 可以直接调用 Java 类库,并且与 Java 代码可以无缝集成。
- IronPython:IronPython 是一个在 .NET 平台上运行的 Python 解释器。它将 Python 代码编译成 .NET 中间语言(CIL),然后在 .NET 运行时上执行。IronPython 可以与 .NET 框架和库进行交互,并且可以通过使用 .NET 语言扩展 Python。
- PyPy:PyPy 是一个用 Python 实现的解释器,它旨在提供更高的性能。PyPy 使用即时(JIT)编译技术来动态优化 Python 代码,并且通常比 CPython 提供更好的性能。
除了这些常见的解释器之外,还有一些其他的 Python 解释器,例如 MicroPython(针对嵌入式系统)、Stackless Python(用于并发编程)、Pyston(用于性能优化)、Nuitka(将 Python 代码编译成 C 或 C++)、Shed Skin(将 Python 代码转换成 C++)等。
来源:https://www.cnblogs.com/aster-ist/p/18014685
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作! |
|