【问题标题】:How to write code points to a file without converting them into string?如何将代码点写入文件而不将它们转换为字符串?
【发布时间】:2020-04-01 12:01:19
【问题描述】:

我有一个包含不同类型字符的 JSON 文件。我将它用于 NLP 项目。我需要将文本加载到字典中,然后将键原样写入另一个文件以进行一些额外的预处理。有问题的文本是数字、字母字符和代码点的混合体。问题是,当我将字典写入文本文件时,如果有意义的话,它会将代码点更改为字符串。所以 \u00a1 变成 ¡\u00a2 变成 ¢ 等等。我想写在代码点中,而不是它们的字符串表示形式。

我要处理的相关文件在这里:https://storage.googleapis.com/gpt-2/encoder.json

这是我用来将字典写入文本文件的代码。

import os
import json

with open(r" file/path/to/encoder.json") as f:
   encoder = json.load(f)
   file1 = open(r"file/path/to/file.txt","a", encoding="utf-8")
   for key in encoder:
      file1.write(key + " " + str(encoder[key]) + '\n')

如何在不更改代码点的情况下编写代码点?

【问题讨论】:

  • 您希望代码点像文字字符串一样编写。 IE print(r'\u00a2') 如果是这样,通过在字符串之前给出字母 r 告诉 python 将其视为原始字符串并且不解释任何特殊含义
  • 链接已损坏,这就是不鼓励在 SO 上使用链接的原因。在问题本身中发布实际文档的样本。
  • 最好的方法是使用酸洗。有了它,您可以检索原始数据,无论您在文件中存储什么类型的数据,加载时都会收到相同类型的数据
  • @GurkiratSingh 除非您担心安全性,并且数据不受信任。阅读pickle docs 中的重大警告。

标签: python python-3.x unicode


【解决方案1】:

如果json 库使用ensure_ascii=True 编写,JSON 会写入那些 Unicode 转义码。当文件再次加载时,它会将它们转换回 Unicode 代码点。

例子:

>>> s = '\u00a1Hello!' # This is an escape code.  It becomes a single code point in the string.
>>> print(s)
¡Hello!
>>> import json
>>> j = json.dumps(s) # default is ensure_ascii=True
>>> print(j) # Non-ASCII code points are written as escape codes.
"\u00a1Hello!"
>>> s = json.loads(j) # Converts back to code points
>>> print(s)
¡Hello!
>>> s = r'\u00a1Hello!' # a raw string does not process escape code.
>>> print(s)
\u00a1Hello!
>>> j = json.dumps(s) 
>>> print(j) # JSON escapes the backslash so it is written literally to the file.
"\\u00a1Hello!"
>>> s = json.loads(j)
>>> print(s)
\u00a1Hello!

因此,要使用 JSON 按您的意愿工作,首先需要正确写入数据。

【讨论】:

    【解决方案2】:

    我找到了一个类似于 OP 所指的文件,如果不完全是,encoder.json

    查看文件,我可以看到 OP 的问题中引用的一些文本:

    {... "\u00a1": 94, "\u00a2": 95, ...}
    

    如果我运行 OP 的代码来将 encoder.json 转换为 file.txt 我确实看到了“将代码点 ("\u00a1") 更改为字符串 ("¡")”的效果。

    但是,这应该不是问题,因为它们的意思是一样的:

    >>> print("¡ 94\n¢ 95")
    ¡ 94
    ¢ 95
    >>> print("\u00a1 94\n\u00a2 95")
    ¡ 94
    ¢ 95
     >>> "¡ 94\n¢ 95"=="\u00a1 94\n\u00a2 95"
    True
    

    在原始 JSON 文件中将字符编码为 un​​icode 转义序列只是 Python 的 JSON 编码器如何工作的一个细节(默认为 ensure_ascii=True):

    >>> json.dumps({"¡": 94, "¢": 95})
    '{"\\u00a1": 94, "\\u00a2": 95}'
    
    >>> json.dumps({"¡": 94,"¢": 95}, ensure_ascii=False)
    '{"¡": 94, "¢": 95}'
    

    如果您使用的是 Python2,则与 u"..." 前缀有点不同(可能更令人困惑):

    >>> print("¡ 94\n¢ 95")
    ¡ 94
    ¢ 95
    >>> print(u"\u00a1 94\n\u00a2 95")
    ¡ 94
    ¢ 95
    >>> u"¡ 94\n¢ 95"==u"\u00a1 94\n\u00a2 95"
    True
    
    >>> # But this is the same
    >>> json.dumps({"¡": 94, "¢": 95})
    '{"\\u00a1": 94, "\\u00a2": 95}'
    
    >>> # But this is a little different
    >>> json.dumps({"¡": 94,"¢": 95}, ensure_ascii=False)
    '{"\xc2\xa1": 94, "\xc2\xa2": 95}'
    
    >>> # But they !! all **mean** the same thing !!
    >>> \
    ... json.loads('{"\xc2\xa1": 94, "\xc2\xa2": 95}') == \
    ... json.loads('{"\\u00a1": 94, "\\u00a2": 95}') == \
    ... json.loads('{"¡": 94, "¢": 95}')
    True
    

    根据我在gpt-2 issue 中读到的内容:

    编码器代码不喜欢空格,所以它们替换空格和其他 带有其他 unicode 字节的空白字符。见encoder.py 详情。

    拥有如下所示的文本文件可能会弄乱您的词汇:

    ...
    \u00a1 94
    \u00a2 95
    ...
    

    您在 NLP 处理链中使用 file.txt 时遇到过实际问题吗?

    【讨论】:

      猜你喜欢
      • 2018-06-03
      • 1970-01-01
      • 1970-01-01
      • 2012-03-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-13
      相关资源
      最近更新 更多