我正试图使用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']
['', '']
...
因此,对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
似乎期望某种迭代器返回一行,但我们传递的是一个在字符基上迭代的字符串,这就是为什么它逐字符解析,解决这个问题的一种方法是生成一个临时文件,但我们不需要,我们只需要传递任何可迭代对象。
请注意以下内容,它只是将字符串拆分为一系列行,然后再将其提供给读取器。
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]
更可读。。。
这非常有效:
import csv
reader = csv.reader(open('./MediaResults.txt'),
delimiter='t')
for row in reader:
print row
csv.reader
的第一个参数应该是:
任何支持迭代器协议并返回字符串的对象每次下一个()方法被称为
根据文档,您传递的是字符串,而不是文件对象。字符串的行为就像单个字符的列表,因此就是您所观察到的行为。
简单问题: csv.reader的输入不需要字符串。
简单解决方案:将输入更改为:data.splitlines()
。
csv阅读器需要一个迭代,每次返回一行。不幸的是,字符串一次迭代一个字符。要解决此问题,请使用splitlines()将字符串转换为行列表:
reader = csv.reader(data.splitlines(), delimiter='t')
for row in reader:
print row
也许您想通过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