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
は、行を返すある種のイテレータを期待しているようですが、文字ベースで反復する文字列を渡しています。これが、文字ごとに解析する理由です。これを修正する1つの方法は、一時ファイルを生成しますが、必要はありません。 どれか 反復可能なオブジェクト。
次の点に注意してください。これは、文字列を行のリストに分割し、それをリーダーに渡す前に行います。
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]
...
簡単な問題:csv.readerは、入力に文字列を予期していませんでした。
シンプルなソリューション:入力をdata.splitlines()
に変更します。
Csvリーダーは、一度に1行ずつ返す反復可能オブジェクトを想定しています。文字列は、残念ながら一度に1文字ずつ反復します。この問題を解決するには、splitlines()を使用して文字列を行のリストに変換します。
reader = csv.reader(data.splitlines(), delimiter='\t')
for row in reader:
print row
これは完全に機能します:
import csv
reader = csv.reader(open('./MediaResults.txt'),
delimiter='\t')
for row in reader:
print row
csv.reader
の最初のパラメーターは次のようになります。
反復子プロトコルをサポートし、そのnext()メソッドが呼び出されるたびに文字列を返すオブジェクト
the docs に従って、ファイルオブジェクトではなく文字列を渡します。文字列は単一の文字のリストとして動作するため、観察されている動作になります。
おそらく、csv APIを通じて方言を嗅ぎたいでしょう:
csvfile = open("example.csv", "rb")
dialect = csv.Sniffer().sniff(csvfile.read(1024))
csvfile.seek(0)
reader = csv.reader(csvfile, dialect)
これにより、正しい出力が生成されます。
こちらもご覧ください