今天我发现了一个内置函数compile
。虽然我读了文档,但仍然不理解它的用法或适用范围。请有人能举个例子来解释一下这个函数的用途吗?如果有例子我将非常感激。
从文档中可以看到,该函数需要一些参数,如下所示。
compile(source, filename, mode[, flags[, dont_inherit]])
这不是常用的函数。当您有Python源代码的字符串形式,并且想将其转换为Python代码对象以便保留和使用时,可以使用该函数。以下是一个简单的例子:
>>> codeobj = compile('x = 2\nprint "X is", x', 'fakemodule', 'exec')
>>> exec(codeobj)
X is 2
基本上,代码对象将一个字符串转换为一个对象,您可以稍后调用exec
来运行字符串中的源代码。(这适用于“ exec”模式;如果字符串包含单个表达式的代码,则“ eval”模式允许使用eval
。)这不是常见的任务,这就是为什么您可能永远不会遇到需要它的情况。
它的主要用途是在元编程或嵌入式环境中。例如,如果您有一个Python程序,允许用户使用自定义Python代码对其行为进行脚本化,您可以使用compile
和exec
来存储和执行这些用户定义的脚本。
compile
很少使用的另一个原因是,像exec
、eval
及其同类一样,compile
是一个潜在的安全漏洞。如果您以字符串形式接收用户代码并将其编译,然后稍后执行它,那么您可能正在运行不安全的代码。(例如,想象一下,在上面的示例中,代码是formatYourHardDrive()
而不是print x
。)
compile
是 exec
和 eval
的低级版本。它不执行或评估您的语句或表达式,而是返回一个可以执行它们的代码对象。模式如下:
compile(string, '', 'eval')
返回的代码对象与您执行 eval(string)
时将要执行的代码对象相同。请注意,您不能在此模式中使用语句;仅一个(单一)表达式是有效的。用于单个表达式。compile(string, '', 'exec')
返回的代码对象与您执行 exec(string)
时将要执行的代码对象相同。您可以在此处使用任意数量的语句。用于整个模块。compile(string, '', 'single')
类似于 exec
模式,但它将忽略除第一条语句以外的所有内容。请注意,带有其结果的 if
/else
语句被视为单个语句。用于一个单独的语句。import ast
from ast import *
myast = ast.parse('''def inc(i):
return i + 1
print(inc(2))
''')
# print(ast.dump(myast, indent=2))
print(ast.unparse(myast))
code = compile(myast, 'mymodule', 'exec')
exec(code)
print()
myast2 = ast.fix_missing_locations(Module(
body=[
FunctionDef(
name='inc',
args=arguments(
posonlyargs=[],
args=[
arg(arg='i')],
kwonlyargs=[],
kw_defaults=[],
defaults=[]),
body=[
Return(
value=BinOp(
left=Name(id='i', ctx=Load()),
op=Add(),
right=Constant(value=1)))],
decorator_list=[]),
Expr(
value=Call(
func=Name(id='print', ctx=Load()),
args=[
Call(
func=Name(id='inc', ctx=Load()),
args=[
Constant(value=2)],
keywords=[])],
keywords=[]))],
type_ignores=[]))
# print(ast.dump(myast2, indent=2))
print(ast.unparse(myast))
code2 = compile(myast2, 'mymodule', 'exec')
exec(code2)
输出:
def inc(i):
return i + 1
print(inc(2))
3
def inc(i):
return i + 1
print(inc(2))
3
ast.*
对象,我们能够以与来自常规Python代码字符串的Python代码相匹配的方式构建完全基于ast树的Python代码。code
对象code
包含什么以及如何检查它,请参阅:在此TypeError消息中提到的“code对象”是什么?
在Python 3.11.4、Ubuntu 23.04上进行了测试。
py1.py
和py2.py
(假设我从数据库单元格中获取这些字符串,用户通过浏览器界面选择这些文件上传),其中py1.py
调用在py2.py
中编写的函数。我该如何处理这种情况? - Mahesha999