【问题标题】:Introducing a YAML string in a python script在 python 脚本中引入 YAML 字符串
【发布时间】:2017-02-20 17:05:43
【问题描述】:

我正在编写能够读取 YAML 文件并在 PySB 中生成基于规则的模型的 python 代码。

YAML 文件中的新规则指定如下:

--- !rule
name: L_binds_R
reaction:
    L(unbound) + R(inactive) >> L(bound)%R(active)
rates:
    - Kf

有了这个,我在 python 中创建了一个 pyyaml 对象(pyyaml 是一个在 python 中使用 yaml 的包),并且反应属性存储为一个字符串。

那么,pysb中的规则需要指定为:

# Rule(name, reaction, constant)
Rule('L_binds_R', L(unbound) + R(inactive) >> L(bound)%R(active), kf)

我的问题在于 yaml 中的“反应”字段作为字符串存储在 python 对象中,但 pysb 不接受纯文本以外的任何其他格式。

我已经在 PySB 中检查过,反应字段在任何情况下都不能是字符串,并且我没有找到如何在 YAML 中转义变量的格式。

有解决问题的办法吗?

【问题讨论】:

  • 您要么必须解析 reaction 字符串并在 Python 中重新构建该表达式,要么使用 eval() 并引入运行任意 Python 代码的能力(如果您的应用程序接受,这是一个巨大的安全漏洞来自不受信任来源的输入)。
  • 什么是“反应”字段? YAML 中既没有字段,Python 中也没有字段。什么是 PyYAML 对象?或者你的意思是你正在使用 PyYAML 创建一个 Python 对象。
  • PySB 使用运算符重载来“使”Python 本身解析直接用 Python 代码编写的规则表达式,因此如果不使用 eval,就没有完全通用的方法来做你想做的事。如果您可以进一步扩展您的总体目标,我们或许可以提出一些替代方法。

标签: python python-2.7 yaml pysb


【解决方案1】:

您可以采用以下两种方法之一:重组您的 YAML 查找以标记化反应规则,或在 Python 中使用 eval

标记化反应规则

最好的方法是构建您的 YAML 文件,以便您的反应规则已经在各个标记中指定,而不是整个反应的一个字段,例如

--- rule!
name: L_binds_R
reaction:
    reactant:
        name: L
        site: b
    reactant:
        name: R
        site: b
            state: inactive         
    product:
        name: L
        site: b
            bond: 1
    product:
        name: R
        site: b
            bond: 1
            state: active
    fwd_rate: kf

然后您可以编写一个解析器将其转换为以下 PySB 规则,使用 PySB 核心中的类(MonomerPatternComplexPattern 等)构建 ReactionPattern

Rule(‘L_binds_R’, L(b=None) + R(b='inactive') >> L(b=1) % R(b=(‘active’, 1)), kf)

如果您可以控制 YAML 的来源代码,您可能会发现直接输出 PySB 代码或写入 SBML 之类的标准(PySB can now read)更容易。

您可能会发现查看我编写的 PySB BioNetGen language (BNGL) parser 会有所帮助,它从 BioNetGen XML 文件创建 PySB 模型,作为如何从外部文件创建模型的示例。

使用eval

替代方法是使用eval。虽然这是更简单的解决方案,但出于安全原因,强烈建议使用*。但是,如果 YAML 文件都是由您/您自己的代码生成的,并且您只想快速修复,那么就可以了。

这是一个例子:

# You would read these in from the YAML file, but I’ll just define
# the strings here for simplicity
reaction_name = "L_binds_R"
reaction_str = "L(b=None) + R(b='inactive') >> L(b=1) % R(b=('active', 1))"
reaction_fwd_rate = "Kf"

Rule(reaction_name, eval(reaction_str), eval(reaction_fwd_rate))
# Python output 
# (assumes Monomers L and R and parameter Kf are already defined):
# >>> Rule('L_binds_R', L(b=None) + R(b='inactive') >> L(b=1) % R(b=('active', 1)), Kf)

*考虑您的 YAML 包含以下内容的情况:

reaction:
    import shutil; shutil.rmtree('~')

导入该 YAML 文件并evaling 该字段将删除您的主目录! eval 将根据定义执行任意 Python 代码。它只应在源文件完全受信任的情况下使用。一般来说,您应该始终“清理您的输入”(假设输入是危险的,除非另有证明)。

【讨论】:

猜你喜欢
  • 2020-04-30
  • 1970-01-01
  • 1970-01-01
  • 2011-11-13
  • 2012-11-22
  • 1970-01-01
  • 1970-01-01
  • 2020-03-27
  • 2017-08-17
相关资源
最近更新 更多