Python中如何避免使用exec函数?
一段源码
import importlib
packages = [‘pathlib’, ‘sys’]
modules = [‘Path’, ‘path’]
for idx, package in enumerate(packages):
tmp = importlib.import_module(package)
importlib.reload(tmp)
execline = modules[idx] + ’ = getattr(tmp, “’ + modules[idx] + '”)’
print(execline)
exec(execline)
# importlib.import_module(‘pathlib’); importlib.reload(pathlib); Path = getattr(pathlib, ‘Path’)
# import pathlib; importlib.reload(pathlib); from pathlib import Path
请问各路高人,有什么办法能替代上面的 exec?
稍微解释一下。exec 那句的功能是要动态载入数个我自己的函数…… 不过我用了系统的包做例子。非动态下 2 行 # 行其中的任一行都可以实现 exec行的功能。
之所以不想用 exec 一是因为 pylint 出警告信息,二是因为 execline 这种写法太丑也容易出错。
Python中如何避免使用exec函数?
用 locals?
帖子标题:Python中如何避免使用exec函数?
避免使用exec,主要因为它有安全风险(动态执行代码可能被注入恶意内容)和调试困难。根据你的需求,这里有几种替代方案:
1. 用字典或getattr动态访问变量
如果你是想根据字符串变量名来获取值,别用exec("value = " + var_name)。
data = {"x": 10, "y": 20}
var_name = "x"
value = data.get(var_name) # 安全地获取值
print(value) # 输出 10
或者用getattr访问对象属性:
class Config:
x = 10
y = 20
config = Config()
attr_name = "x"
value = getattr(config, attr_name, None) # 安全获取属性
print(value) # 输出 10
2. 用函数映射代替动态代码生成
如果你有一堆条件操作,别用exec生成代码块,用字典把操作映射到函数。
def action_a():
return "执行操作A"
def action_b():
return "执行操作B"
actions = {"a": action_a, "b": action_b}
choice = "a"
if choice in actions:
result = actions[choice]() # 调用对应的函数
print(result) # 输出 "执行操作A"
3. 用eval(有限制地)代替exec
如果只是计算表达式(不是语句),并且输入可信,可以用eval,但同样要小心。
expression = "3 * 5 + 2"
result = eval(expression) # 只计算表达式
print(result) # 输出 17
注意:eval也只该用在可信环境,或者用ast.literal_eval处理字面量。
4. 用importlib动态导入模块
如果是想根据字符串导入模块,用importlib。
import importlib
module_name = "math"
module = importlib.import_module(module_name)
print(module.sqrt(16)) # 输出 4.0
总结建议:根据具体场景选择字典、函数映射或安全的内置函数来替代exec。
大侠可不可以说仔细一点,感谢。
eval(…) 一般都可以用 dict 和 getattrib 实现,我在找实现 exec(…) 办法。网上好像说 eval 和 exec 都可以用别的办法代替。
locals()[“func_name”]
参见
importlib.util.module_from_spec
和
importlib.util.spec_from_file_location
感谢,我研究一下……
感谢,我 google 一下
locals()[“func_name”] 只是拿到 module 的名字,其实是源码里的 tmp, 可我要的是 module 的 方法(给定’pathlib’ 和 ‘Path’, 实现 from pathlib import Path)。
importlib.util.module_from_spec 和 importlib.util.spec_from_file_location 貌似都搜索 module 的名字。可我要的是 module 的 方法(例如,给定’pathlib’ 和 ‘Path’, 实现 from pathlib import Path)。
请各路高人继续支招,先感谢。
我再简化一下问题,考虑下面的源码
module_name = 'pathlib’
tmp = importlib.import_module(module_name) # 等效 import pathlib; tmp = pathlib
importlib.reload(tmp) # 等效 importlib.reload(pathlib)
? ?? # 如何不用 exec 实现 from pathlib import Path?
# 用 exec 的话可以凑一个 execline = “Path = getattr(tmp, ‘Path’)” 送给 exec(execline)
# 等效运行了 Path = getattrib(pathlib, ‘Pah’) , 等效于 from pathlib import Path
等下 你要限定这个函数叫 Path。。。那我不知道了
再直接 moudle.dict[fun_name]就可以了啊,我有种感觉你应该没什么 python 的经验……,那些函数只是普通变量,你获得函数变量后想怎么命名就怎么命名啊
感谢楼上各位。
我想我知道怎么做了。8 楼问题的答案是:
globals()[‘Path’] = getattrib(tmp, ‘Path’)
0 楼的 exec 行可以用下面的码代替:
globals()[modules[idx]] = getattrib(tmp, modules[idx])
google “动态导入模块”
感觉问题有点误导. 核心是如何替代 exec 里的 assign. 和 import module 啥的关系都不大.
是啊,有些大侠不审题就给答案 ;), 而且提的问题里已经用了 importlib。不过还是感谢各位……
哈哈哈哈哈,原来你的核心问题就是如何动态创建一个名为 xxx 的变量。那 locals 和 globals 都可以,具体就看你想要的作用范围啦。哈哈哈哈哈


