【问题标题】:Tab-delimited file using csv.reader not delimiting where I expect it to使用 csv.reader 的制表符分隔文件未在我期望的位置分隔
【发布时间】:2012-08-21 15:19:03
【问题描述】:

我正在尝试使用 Python 循环遍历以制表符分隔的选举结果文件。以下代码不起作用,但是当我使用具有相同结果的本地文件(注释掉的行)时,它确实按预期工作。

我唯一能想到的是一些标题或内容类型我需要传递 url,但我无法弄清楚。

为什么会这样?

import csv
import requests

r = requests.get('http://vote.wa.gov/results/current/export/MediaResults.txt') 
data = r.text
#data = open('data/MediaResults.txt', 'r')
reader = csv.reader(data, delimiter='\t')
for row in reader:
    print row

结果:

...
['', '']
['', '']
['2']
['3']
['1']
['1']
['8']
['', '']
['D']
['a']
['v']
['i']
['d']
[' ']
['F']
['r']
['a']
['z']
['i']
['e']
['', '']
...

【问题讨论】:

    标签: python csv python-requests


    【解决方案1】:

    也许你想通过 csv API 来嗅探方言:

    csvfile = open("example.csv", "rb")
    dialect = csv.Sniffer().sniff(csvfile.read(1024))
    csvfile.seek(0)
    reader = csv.reader(csvfile, dialect)
    

    这将产生正确的输出。

    另见

    http://docs.python.org/library/csv.html#csv.Sniffer

    【讨论】:

    • 原来其实是直接把数据传给reader()构造函数而不是文件句柄。
    【解决方案2】:

    这很好用:

    import csv
    
    reader = csv.reader(open('./MediaResults.txt'),
                        delimiter='\t')
    for row in reader:
        print row
    

    csv.reader的第一个参数应该是:

    任何支持迭代器协议并返回字符串的对象 每次调用它的 next() 方法时

    根据the docs,您传递的是字符串,而不是文件对象。字符串表现为单个字符的列表,因此是您观察到的行为。

    【讨论】:

      【解决方案3】:

      所以发生了什么,好吧,致电help 可能会有所启发。

      >>> help(csv.reader)
       reader(...)
          csv_reader = reader(iterable [, dialect='excel']
                                  [optional keyword args])
              for row in csv_reader:
                  process(row)
      
          The "iterable" argument can be any object that returns a line
          of input for each iteration, such as a file object or a list.  The
          optional "dialect" parameter is discussed below.  The function
          also accepts optional keyword arguments which override settings
          provided by the dialect.
      

      所以看来csv.reader 期望某种类型的迭代器将返回一行,但我们传递了一个在 char 基础上迭代的字符串,这就是为什么它逐个字符解析的原因,解决此问题的一种方法是生成一个临时文件,但我们不需要,我们只需要传递 any 可迭代对象。

      请注意以下内容,它只是将字符串拆分为行列表,然后再将其提供给阅读器。

      import csv
      import requests
      
      r = requests.get('http://vote.wa.gov/results/current/export/MediaResults.txt') 
      data = r.text
      reader = csv.reader(data.splitlines(), delimiter='\t')
      for row in reader:
          print row
      

      这似乎有效。

      我还建议使用csv.DictReader,它非常有用。

      >>> reader = csv.DictReader(data.splitlines(), delimiter='\t')
      >>> for row in reader:
      ...      print row
      {'Votes': '417141', 'BallotName': 'Michael Baumgartner', 'RaceID': '2', 'RaceName': 'U.S. Senator', 'PartyName': '(Prefers Republican Party)', 'TotalBallotsCastByRace': '1387059', 'RaceJurisdictionTypeName': 'Federal', 'BallotID': '23036'}
      {'Votes': '15005', 'BallotName': 'Will Baker', 'RaceID': '2', 'RaceName': 'U.S. Senator', 'PartyName': '(Prefers Reform Party)', 'TotalBallotsCastByRace': '1387059', 'RaceJurisdictionTypeName': 'Federal', 'BallotID': '27435'}
      

      基本上它为每一行返回一个字典,使用标题作为键,这样我们就不需要跟踪顺序,而只是名称让我们更容易一些,即row['Votes'] 似乎更具可读性然后row[4]...

      【讨论】:

        【解决方案4】:

        简单的问题: csv.reader 不希望输入字符串。

        简单的解决方案:将输入改为:data.splitlines()

        csv 阅读器需要一个迭代器,它一次返回一行。不幸的是,字符串一次迭代一个字符。为了解决这个问题,使用 splitlines() 将字符串变成行列表:

        reader = csv.reader(data.splitlines(), delimiter='\t')
        for row in reader:
            print row
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-09-22
          • 2020-10-12
          • 2014-10-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多