阅读 Software Carpentry 后关于Handling Configuration Files的文章我对他们的方法#5:将参数放入动态加载的代码模块感兴趣。基本上,我希望能够在输入文件中进行计算以创建变量。
基于 how to import a string as a module 的 SO 答案我编写了以下函数来将字符串或 oen 文件对象或 STringIO 作为模块导入。然后我可以使用 .运算符:
import imp
def make_module_from_text(reader):
"""make a module from file,StringIO, text etc
Parameters
----------
reader : file_like object
object to get text from
Returns
-------
m: module
text as module
"""
#for making module out of strings/files see https://stackoverflow.com/a/7548190/2530083
mymodule = imp.new_module('mymodule') #may need to randomise the name; not sure
exec reader in mymodule.__dict__
return mymodule
然后
import textwrap
reader = textwrap.dedent("""\
import numpy as np
a = np.array([0,4,6,7], dtype=float)
a_normalise = a/a[-1]
""")
mymod = make_module_from_text(reader)
print(mymod.a_normalise)
给出
[ 0. 0.57142857 0.85714286 1. ]
到目前为止一切都很好,但是环顾四周,如果我不信任输入,使用 python eval
和 exec
似乎会引入安全漏洞。常见的 react 是“永远不要使用 eval 或 exec;它们是邪恶的”,但我真的很喜欢执行代码的强大功能和灵活性。使用 {'__builtins__': None}
我认为这对我不起作用,因为我想导入其他模块(例如,在我上面的代码中 import numpy as np
) 。许多人(例如 here )建议使用 ast
模块,但我完全不清楚如何使用它(ast
可以与 一起使用吗?执行
?)。是否有简单的方法来白名单/允许特定功能(例如 here )?是否有简单的方法可以将特定功能列入黑名单/禁止?有没有一种神奇的方法可以说执行此操作但不要做任何令人讨厌的事情。
基本上,有哪些选项可以确保 exec
不会运行任何令人讨厌的恶意代码?
编辑:
上面我在输入/配置文件中规范化数组的示例对于我想要在输入/配置文件中执行的计算可能有点简单化(我可以轻松地在程序中编写一个方法/函数来执行那)。但是假设我的程序在不同时间计算一个属性。用户需要以某种方式指定时间。我是否应该只接受明确的时间值列表,以便用户在准备输入文件之前必须进行一些计算? (注意:即使使用列表作为配置变量也不是微不足道的 see here )。我认为这是非常有限的。我应该允许开始-结束步骤值,然后在程序中使用 numpy.linspace 吗?我认为这也是有限制的。如果我想使用 numpy.logspace 代替怎么办?如果我有一些函数可以接受重要时间值的列表,然后很好地填充其他时间以获得间隔良好的时间值,该怎么办?如果用户能够导入该函数并使用它,这不是很好吗?如果我想输入用户定义对象的列表怎么办?问题是,当 python 的功能已经可供我和我的用户使用时,我不想为所有这些特定情况编写代码。一旦我承认我确实想要在输入/配置文件中执行代码的能力和功能,我想知道使用 exec
与使用 importlib< 在安全方面实际上是否有任何区别
vs imp.load_source等等。对我来说,有有限的标准配置解析器或功能强大、危险的执行器。我只是希望有一些中间立场,我可以说“执行这个......而不填满我的计算机”。
最佳答案
“永远不要使用 eval 或 exec;它们是邪恶的”。我认为这是唯一在这里有效的答案。没有完全安全的方法可以对不受信任的字符串或文件使用 exec/eval。
你能做的最好的事情就是想出你自己的语言,要么自己解释它,要么在处理它执行之前将其转换为安全的Python代码。从头开始要小心 --- 如果您允许整个 Python 语言减去您认为危险的特定内容,那么它永远不会真正安全。
例如,如果你想要类似Python的语法,你可以使用ast模块;然后编写一个小的自定义 ast 解释器,它只能识别所有可能节点的一小部分。这是最安全的解决方案。
关于python - 如何安全使用exec?我想使用动态加载的代码模块作为配置文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19721027/