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函数?

19 回复

用 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

tmp.dict[‘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 都可以,具体就看你想要的作用范围啦。哈哈哈哈哈

回到顶部