【问题标题】:How to read bytes object from csv?如何从 csv 读取字节对象?
【发布时间】:2017-12-10 17:03:17
【问题描述】:

我使用 tweepy 将推文的文本存储在使用 Python csv.writer( 的 csv 文件中,但我必须在存储之前将文本编码为 utf-8,否则 tweepy 会抛出一个奇怪的错误。

现在,文本数据是这样存储的:

"b'Lorem Ipsum\xc2\xa0Assignment '"

我尝试使用此代码对此进行解码(其他列中有更多数据,文本在第 3 列):

with open('data.csv','rt',encoding='utf-8') as f:
    reader = csv.reader(f,delimiter=',')
    for row in reader:
        print(row[3])

但是,它不会对文本进行解码。我不能使用.decode('utf-8'),因为csv阅读器将数据读取为字符串,即type(row[3])'str',我似乎无法将其转换为bytes,数据再次被编码!

如何解码文本数据?

编辑:这是 csv 文件中的示例行:

67783591545656656999,3415844,1450443669.0,b'Virginia School District Closes After Backlash Over Arabic Assignment: The Augusta County school district in\xe2\x80\xa6  | @abcde',52,18

注意:如果解决方案是在编码过程中,请注意我不能再次下载整个数据。

【问题讨论】:

  • 如果您在文本编辑器中打开该文件,请至少显示文件中完整的一行。没有您的代码和数据,我们无法重现您的问题。
  • 对不起。我添加了一个例子。将该行保存在扩展名为 .csv 的文件中。
  • 所以 csv 文件中确实有字符串,这些字符串用 b 前缀表示,例如 b'Virginia...'?
  • 导致 CSV 损坏的任何东西都应该修复。

标签: python python-3.x


【解决方案1】:

如果您的输入文件确实包含带有 Python 语法 b 前缀的字符串,一种解决方法(即使它不是真正包含 csv 数据的有效格式)是使用 Python 的 ast.literal_eval 函数 @ Ryan 提到虽然我会以稍微不同的方式使用它,如下所示。

这将提供一种安全的方法来解析文件中以b 为前缀的字符串,表明它们是字节字符串。其余的将原封不动地通过。

import ast
import csv


def _parse_bytes(field):
    """ Convert string represented in Python byte-string literal b'' syntax into
        a decoded character string - otherwise return it unchanged.
    """
    result = field
    try:
        result = ast.literal_eval(field)
    finally:
        return result.decode() if isinstance(result, bytes) else field


def my_csv_reader(filename, /, **kwargs):
    with open(filename, 'rt', newline='') as file:
        for row in csv.reader(file, **kwargs):
            yield [_parse_bytes(field) for field in row]


reader = my_csv_reader('bytes_data.csv', delimiter=',')
for row in reader:
    print(row)

【讨论】:

  • 谢谢。这确实解决了上述情况,但我对使用 eval() 感到不舒服。它甚至在我的文件上失败,因为它有标题字符串。
  • gitmorty:我认为@Ryan 使用ast.literal_eval() 而不是eval() 的想法是一个很好的想法,并且已将基本想法纳入我自己的答案中——我认为这解决了您在你的评论。
【解决方案2】:

最简单的方法如下。试试看。

import csv
from io import StringIO

byte_content = b"iam byte content"
content = byte_content.decode()
file = StringIO(content)
csv_data = csv.reader(file, delimiter=",")

【讨论】:

    【解决方案3】:

    您可以使用ast.literal_eval 将不正确的字段安全地转换回字节:

    import ast
    
    
    def _parse_bytes(bytes_repr):
        result = ast.literal_eval(bytes_repr)
    
        if not isinstance(result, bytes):
            raise ValueError("Malformed bytes repr")
    
        return result
    

    【讨论】:

      猜你喜欢
      • 2018-01-25
      • 1970-01-01
      • 2021-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-30
      • 1970-01-01
      • 2020-01-23
      相关资源
      最近更新 更多