在复杂应用程序的上下文中,我需要导入用户提供的"脚本".理想情况下,脚本应该

def init():
    blah

def execute():
    more blah

def cleanup():
    yadda

所以我就

import imp
fname, path, desc = imp.find_module(userscript)
foo = imp.load_module(userscript, fname, path, desc)
foo.init()

然而,正如我们所知,只要运行load_module次,用户的脚本就是executed.

def init():
    blah

yadda

屈服于我一看完 playbook 就被调用的yadda部分.

我需要的是一种方法:

  1. 首先判断它是否有init()、execute()和cleanup()
  2. 如果它们存在,一切都很好
  3. 如果它们不存在,就抱怨吧
  4. 不要运行任何其他代码,或者至少在我知道没有init()之前不要运行

通常情况下,我会强制使用相同的老if __name__ == '__main__'技巧,但我对用户提供的脚本几乎没有控制权,所以我正在寻找一个相对轻松的解决方案.我见过各种复杂的技巧,包括解析脚本,但没有什么真正简单的.我很惊讶它不存在..或者也许我没有得到什么.

谢谢

推荐答案

我try 使用ast模块:

import ast

# which syntax elements are allowed at module level?
whitelist = [
  # docstring
  lambda x: isinstance(x, ast.Expr) \
             and isinstance(x.value, ast.Str),
  # import
  lambda x: isinstance(x, ast.Import),
  # class
  lambda x: isinstance(x, ast.ClassDef),
  # function
  lambda x: isinstance(x, ast.FunctionDef),
]

def validate(source, required_functions):
  tree = ast.parse(source)

  functions = set()
  required_functions = set(required_functions)

  for item in tree.body:
    if isinstance(item, ast.FunctionDef):
      functions.add(item.name)
      continue

    if all(not checker(item) for checker in whitelist):
      return False

  # at least the required functions must be there
  return len(required_functions - functions) == 0


if __name__ == "__main__":
  required_funcs = [ "init", "execute", "cleanup" ]
  with open("/tmp/test.py", "rb") as f:
    print("yay!" if validate(f.read(), required_funcs) else "d'oh!")

Python-3.x相关问答推荐

向前/向后移动导致移动行的数据不可见

Heroku 中的未知错误代码缺少一个或多个参数

SQL Server 2022和Python3.10脚本错误

你能骗PIP 让它相信包已经安装了吗

通过匹配第一列的行值,逐个单元格地添加两个Pandas 数据框中的浮点数

如何使用 django rest 框架在 self forienkey 中删除多达 n 种类型的数据?

如果值超出上下限(异常值处理),则将值的数据框替换为 np.nan

魔术8球txt文件列表

python中两个连续的yield语句如何工作?

参数化泛型不能与类或实例判断一起使用

Seaborn 热图 colored颜色 条标签作为百分比

如何使用pandas python获取数据框中每列的最大长度

ValueError:FixedLocator 位置的数量 (5),通常来自对 set_ticks 的调用,与刻度标签的数量 (12) 不匹配

Python 3 变量名中接受哪些 Unicode 符号?

使用逗号时,除了处理程序中的语法无效

迭代dict值

如何在 python 3.x 中禁用 ssl 判断?

在 ubuntu 20.04 中安装 libpq-dev 时出现问题

将列表列表转换为Python中的字典字典

首次使用后 zip 变量为空