【问题标题】:Running JSON through Python's eval()?通过 Python 的 eval() 运行 JSON?
【发布时间】:2015-02-06 02:26:45
【问题描述】:

除了最佳实践,是否有令人信服的理由这样做?

我正在编写一个用于 Google 代码项目的提交后挂钩,该项目通过 JSON 对象提供提交数据。 GC 随请求提供了一个 HMAC 身份验证令牌(在 JSON 数据之外),因此通过验证该令牌,我非常确信 JSON 数据既是良性的(因为不信任 Google 没有什么意义)并且是有效的。

我自己的(简要)调查表明,JSON 恰好是完全有效的 Python,但 "\/" 转义序列除外 - GC 似乎不会生成该序列。

所以,当我使用 Python 2.4(即没有 json 模块)时,eval() 看起来真的很诱人。

编辑:郑重声明,我非常询问这是否是个好主意。我非常知道它不是,我非常怀疑我是否会在任何未来的项目中使用这种技术,即使我最终将它用于这个项目。我只是想确保我知道如果我这样做会遇到什么样的麻烦。 :-)

【问题讨论】:

    标签: python json


    【解决方案1】:

    如果您对自己的脚本可以正常工作一段时间感到满意,然后在一些模糊的边缘情况下随机失败,我会选择 eval。

    如果您的代码健壮很重要,我会花时间添加 simplejson。您不需要 C 部分来加速,因此将一些 .py 文件转储到某个目录中并不难。

    举个例子,JSON 使用 Unicode,simplejson 返回 Unicode,而 eval 返回 str:

    >>> simplejson.loads('{"a":1, "b":2}')
    {u'a': 1, u'b': 2}
    >>> eval('{"a":1, "b":2}')
    {'a': 1, 'b': 2}
    

    编辑:eval() 行为不同的更好示例:

    >>> simplejson.loads('{"X": "\uabcd"}')
    {u'X': u'\uabcd'}
    >>> eval('{"X": "\uabcd"}')
    {'X': '\\uabcd'}
    >>> simplejson.loads('{"X": "\uabcd"}') == eval('{"X": "\uabcd"}')
    False
    

    编辑 2:今天看到 SilentGhost 指出的另一个问题:eval 不能正确处理 true -> True, false -> False, null -> None。

    >>> simplejson.loads('[false, true, null]')
    [False, True, None]
    >>> eval('[false, true, null]')
    Traceback (most recent call last):
      File "<interactive input>", line 1, in <module>
      File "<string>", line 1, in <module>
    NameError: name 'false' is not defined
    >>> 
    

    【讨论】:

    • +1 表示“在一些模糊的边缘情况下失败”。你也对 Unicode 提出了一个很好的观点。我很确定它与我的特定用例无关,但这是我以前没有考虑过的。
    • 有趣;我可以发誓我尝试了 \uXXXX 转义码并让它们工作。现在测试它们,正如您在此处显示的那样,它们会失败。我一定是产生了幻觉。 ^.^
    • 如果你确实使用了 C 加速,那么 simplejson 可以返回字符串和 unicode 的混合,这似乎没有兴趣修复 -- code.google.com/p/simplejson/issues/detail?id=40
    • 哇,这真的很奇怪。
    • 对 true/false/null 文字的简单修复:eval('[false, true, null]', {'false': False, 'true': True, 'null': None}) 请注意,无论如何您都应该为全局变量发送 something 以防止访问您的全局变量
    【解决方案2】:

    最佳做法的意义在于,在大多数情况下,忽视它们是个坏主意。如果我是你,我会使用解析器将 JSON 解析为 Python。试试simplejson,当我上次尝试解析 JSON 时,它非常简单,并且声称与 Python 2.4 兼容。

    我不同意不信任 Google 的观点。我不会不信任他们,但我会验证您从他们那里获得的数据。我实际使用 JSON 解析器的原因就在您的问题中:

    我自己的(简短的)调查表明,JSON 恰好是完全有效的 Python,但“/”转义序列除外——GC 似乎不会生成该序列。

    是什么让您认为 Google 代码永远不会生成这样的转义序列?

    如果您使用正确的工具,解析是一个已解决的问题。如果你试图走这样的捷径,你最终会被错误的假设所困扰,或者当你选择的语言已经存在解析器时,你会尝试将解析器与正则表达式和布尔逻辑组合在一起。

    【讨论】:

    • 如果我不在托管环境中运行,我可能使用 simplejson。不幸的是,我对我的 Python 环境没有太多控制权,而且我怀疑弄清楚如何添加自定义包将比编写实际脚本花费更长的时间;我们说的是 50 行,上衣。同样,我知道 GC 不会开始生成该转义序列,但如果确实如此,脚本自然会安全失败,很明显它已损坏,修复方法是容易。
    • 如果修复很容易,为什么不先按照固定的方式进行呢?
    • 因为它涉及使用正则表达式来计算反斜杠。现在,脚本中没有任何正则表达式,如果可以的话,我会保持这种状态。 :-)
    • 这是一个纯 python 中的 simplejson 端口,用于与您类似的情况:aaronland.info/python/s60-simplejson/s60-simplejson.py。我从未使用过它,但我怀疑它比 eval()ing 更好
    • 端口看起来不错。可能值得从原始的 simplejson 运行单元测试,看看它们是否通过:simplejson.googlecode.com/svn/tags/simplejson-2.0.9/simplejson/…
    【解决方案3】:

    一个主要区别是 JSON 中的布尔值是 true|false,但 Python 使用 True|False

    不这样做的最重要原因可以概括为:eval 永远不应该用于解释外部输入,因为这允许任意代码执行。

    【讨论】:

      【解决方案4】:

      evaling JSON 有点像尝试通过 C++ 编译器运行 XML。

      eval 用于评估 Python 代码。尽管有一些语法上的相似之处,JSON 不是 Python 代码。哎呀,它不仅不是 Python 代码,而且一开始也不是代码。因此,即使您可以为您的用例摆脱它,我认为这在概念上是一个坏主意。 Python 是苹果,JSON 是橙味汽水。

      【讨论】:

      • 你只是让我想通过 C++ 编译器运行 XML,看看我是否可以编译它。哦模板。
      猜你喜欢
      • 2016-01-19
      • 2011-08-07
      • 2020-02-01
      • 2023-04-08
      • 2016-07-15
      • 1970-01-01
      • 1970-01-01
      • 2017-09-08
      • 2020-07-01
      相关资源
      最近更新 更多