【问题标题】:Python SimpleCookie and JSON ValuePython SimpleCookie 和 JSON 值
【发布时间】:2016-07-05 14:40:10
【问题描述】:

在使用 JSON 字符串作为值时,我在使用 Python 的 SimpleCookie 时遇到了一些问题。

In [1]: from http.cookies import SimpleCookie

In [2]: cookie = SimpleCookie('x=1; json={"myVal":1}; y=2')

In [3]: cookie.keys()
Out[3]: dict_keys(['x'])

In [4]: cookie = SimpleCookie('x=1; y=2')

In [5]: cookie.keys()
Out[5]: dict_keys(['y', 'x'])

不仅缺少 JSON 字符串,还缺少其他所有值。我现在想知道这是否是与 Python 相关的错误,因为字符应该都可以在 cookie 中使用?

【问题讨论】:

    标签: python python-3.x cookies httpcookie


    【解决方案1】:

    目前您正在尝试使用一个对象作为值,而不是该对象的 JSON 字符串表示。您需要对参数字符串中的 JSON 字符串进行转义,如下所示:

    >>> from http.cookies import SimpleCookie
    >>> cookie = SimpleCookie(r'x=1; json="{\"myVal\":1}"; y=2')
                            # ^ note raw string    ^ and single backslashes
    >>> cookie.keys()
    dict_keys(['json', 'x', 'y'])
    

    一个畸形的字符串被尽可能地安静地消耗掉,而其余的则被丢弃,这似乎很奇怪。我希望您有 ValueError 或其他内容。 The parser 只是停止并返回到目前为止的结果,当它用完与正则表达式匹配的东西时。


    鉴于Marius's answer,它似乎适用于 3.3.2 但不适用于 3.5.2(而且,在我看来,它似乎不应该在任何地方工作;一个隐含的JSON包导入?!)我去寻找它何时改变。使用这个脚本:

    from http.cookies import SimpleCookie
    import json
    from sys import version
    
    print(version)
    
    cookie1 = SimpleCookie('x=1; json=json.dumps({"myVal":1}); y=2')
    print('Marius  ', cookie1.keys(), repr(cookie1.get('json')), sep='\t')
    
    cookie2 = SimpleCookie(r'x=1; json="{\"myVal\":1}"; y=2')
    print('Jonathan', cookie2.keys(), repr(cookie2.get('json')), sep='\t')
    
    cookie3 = SimpleCookie('x=1; json={"myVal":1}; y=2')
    print('Bernhard', cookie3.keys(), repr(cookie3.get('json')), sep='\t')
    

    pyenv 在 Mac OS X 上为 3.3 提供以下结果:

    3.3.0 (default, Jul  7 2016, 10:47:41)
    [GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.72)]
    Marius      dict_keys(['x', 'y', 'json'])   <Morsel: json='json.dumps({'>
    Jonathan    dict_keys(['x', 'y', 'json'])   <Morsel: json='{"myVal":1}'>
    Bernhard    dict_keys(['x', 'y', 'json'])   <Morsel: json='{'>
    
    3.3.1 (default, Jul  7 2016, 10:53:06)
    [GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.72)]
    Marius      dict_keys(['json', 'x', 'y'])   <Morsel: json='json.dumps({'>
    Jonathan    dict_keys(['json', 'x', 'y'])   <Morsel: json='{"myVal":1}'>
    Bernhard    dict_keys(['json', 'x', 'y'])   <Morsel: json='{'>
    
    3.3.2 (default, Jul  6 2016, 22:02:23)
    [GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.72)]
    Marius      dict_keys(['json', 'y', 'x'])   <Morsel: json='json.dumps({'>
    Jonathan    dict_keys(['json', 'y', 'x'])   <Morsel: json='{"myVal":1}'>
    Bernhard    dict_keys(['json', 'y', 'x'])   <Morsel: json='{'>
    
    # ...loses 'json'
    
    3.3.3 (default, Jul  7 2016, 10:57:02)
    [GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.72)]
    Marius      dict_keys(['x', 'y'])   None
    Jonathan    dict_keys(['x', 'y', 'json'])   <Morsel: json='{"myVal":1}'>
    Bernhard    dict_keys(['x', 'y'])   None
    
    3.3.4 (default, Jul  7 2016, 10:59:21)
    [GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.72)]
    Marius      dict_keys(['y', 'x'])   None
    Jonathan    dict_keys(['y', 'x', 'json'])   <Morsel: json='{"myVal":1}'>
    Bernhard    dict_keys(['y', 'x'])   None
    
    3.3.5 (default, Jul  7 2016, 11:01:45)
    [GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.72)]
    Marius      dict_keys(['y', 'x'])   None
    Jonathan    dict_keys(['json', 'y', 'x'])   <Morsel: json='{"myVal":1}'>
    Bernhard    dict_keys(['y', 'x'])   None
    
    # ...and now 'y'!
    
    3.3.6 (default, Jul  7 2016, 11:03:40)
    [GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.72)]
    Marius      dict_keys(['x'])    None
    Jonathan    dict_keys(['json', 'x', 'y'])   <Morsel: json='{"myVal":1}'>
    Bernhard    dict_keys(['x'])    None
    

    从那里看起来很稳定:

    3.4.4 (default, Jul  7 2016, 11:13:43)
    [GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.72)]
    Marius      dict_keys(['x'])    None
    Jonathan    dict_keys(['json', 'y', 'x'])   <Morsel: json='{"myVal":1}'>
    Bernhard    dict_keys(['x'])    None
    
    3.5.2 (v3.5.2:4def2a2901a5, Jun 26 2016, 10:47:25)
    [GCC 4.2.1 (Apple Inc. build 5666) (dot 3)]
    Marius      dict_keys(['x'])    None
    Jonathan    dict_keys(['x', 'json', 'y'])   <Morsel: json="{\"myVal\":1}">
    Bernhard    dict_keys(['x'])    None
    

    3.3.6 以后的版本显然是一个安全修复;见this bug report。这在 3.2.6 中也有应用,所以:

    3.2.4 (default, Jul  7 2016, 11:05:33)
    [GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.72)]
    Marius      dict_keys(['y', 'x', 'json'])   <Morsel: json='json.dumps({'>
    Jonathan    dict_keys(['y', 'x', 'json'])   <Morsel: json='{"myVal":1}'>
    Bernhard    dict_keys(['y', 'x', 'json'])   <Morsel: json='{'>
    
    3.2.5 (default, Jul  7 2016, 11:07:15)
    [GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.72)]
    Marius      dict_keys(['y', 'x', 'json'])   <Morsel: json='json.dumps({'>
    Jonathan    dict_keys(['y', 'x', 'json'])   <Morsel: json='{"myVal":1}'>
    Bernhard    dict_keys(['y', 'x', 'json'])   <Morsel: json='{'>
    
    # ...loses 'y'?!
    
    3.2.6 (default, Jul  7 2016, 11:09:00)
    [GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.72)]
    Marius      dict_keys(['x', 'json'])    <Morsel: json='json.dumps({'>
    Jonathan    dict_keys(['y', 'x', 'json'])   <Morsel: json='{"myVal":1}'>
    Bernhard    dict_keys(['x', 'json'])    <Morsel: json='{'>
    

    此行为与具有相同错误修复的 3.3.6不同!实际上,它将 cookie 中的 json 的值设置为 '{',丢弃该值的其余部分和 y

    我的结论是:

    1. 我的版本适用范围更广;
    2. Marius 的版本实际上对 OP 没有帮助,因为它的键与原始版本相同;和
    3. 3.2 和 3.3 中的此功能发生了一些奇怪的事情!

    【讨论】:

      【解决方案2】:

      这包括 'json' 作为 Python 3.3.2 及更早版本中的键:

      >>> import json
      >>> from http.cookies import SimpleCookie
      >>> cookie = SimpleCookie('x=1; json=json.dumps({"myVal":1}); y=2')
      >>> cookie.keys()
      dict_keys(['y', 'x', 'json'])
      

      但是,该值可能与预期不同:

      >>> print(cookie)
      Set-Cookie: json=json.dumps({
      Set-Cookie: x=1
      Set-Cookie: y=2
      

      【讨论】:

      • 你是对的:我应该添加 import json 行。我已经测试过了,输出是正确的。
      • 我使用 Python 3.3.2 版本
      • 好吧,我已经彻底纠正了,必须安装 pyenv 才能获得 3.3.2 解释器。我很抱歉,现在必须去找出发生变化的时间和原因(以及为什么文档似乎没有提到它)。
      • 我已经更新了我对整个 3.3 行的答案 - 你的版本可以工作到 3.3.2,然后是 3.3.3-3.3.5 的第三种行为,然后是 3.3.6 我见 3.4 和 3.5。很奇怪。
      猜你喜欢
      • 1970-01-01
      • 2020-12-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多