Python 使用csv.reader的制表符分隔的文件未在预期的位置进行分隔

Python 使用csv.reader的制表符分隔的文件未在预期的位置进行分隔,python,csv,python-requests,Python,Csv,Python Requests,我正在尝试使用Python循环遍历一个以制表符分隔的选举结果文件。下面的代码不起作用,但当我使用具有相同结果的本地文件(注释掉的行)时,它确实能按预期工作 我唯一能想到的是我需要传递url的一些标题或内容类型,但我无法理解 为什么会这样 import csv import requests r = requests.get('http://vote.wa.gov/results/current/export/MediaResults.txt') data = r.text #data = o

我正在尝试使用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']
['', '']
...

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

csvfile = open("example.csv", "rb")
dialect = csv.Sniffer().sniff(csvfile.read(1024))
csvfile.seek(0)
reader = csv.reader(csvfile, dialect)
这将产生正确的输出

另见

这项功能非常有效:

import csv

reader = csv.reader(open('./MediaResults.txt'),
                    delimiter='\t')
for row in reader:
    print row
csv.reader
的第一个参数应该是:

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


根据,传递的是字符串,而不是文件对象。字符串的行为类似于单个字符的列表,因此就是您所观察到的行为。

因此,调用
帮助
可能会有所帮助

>>> 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
似乎需要某种类型的迭代器来返回一行,但我们正在传递一个字符串,该字符串以字符为基础进行迭代,这就是它逐个字符解析的原因,解决这个问题的一种方法是生成一个临时文件,但我们不需要,我们只需要传递任何iterable对象

请注意以下内容,它只是将字符串拆分为一列行,然后再将其馈送给读取器

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'}

基本上,它会为每一行返回一个字典,使用标题作为键,这样我们就不需要跟踪顺序,而只需要名称,这样对我们来说就更容易了,即
行['vowers']
看起来比
行[4]更可读

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

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

csv读取器需要一个每次返回一行的iterable。不幸的是,字符串一次迭代一个字符。要解决此问题,请使用splitlines()将字符串转换为行列表:

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

事实上,最初是将数据直接传递给reader()构造函数,而不是文件句柄。