2012-08-27 7 views
13

Sto provando a scorrere un file delimitato da tabulazioni di risultati delle elezioni usando Python. Il seguente codice non funziona, ma quando uso un file locale con gli stessi risultati (la linea commentata), funziona come previsto.File delimitato da tabulati che usa csv.reader non delimitando dove mi aspetto che sia

L'unica cosa che posso pensare sono alcune intestazioni o tipo di contenuto che ho bisogno di passare l'url, ma non riesco a capirlo.

Perché sta succedendo?

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 

Risultati in:

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

risposta

29

così che cosa sta succedendo, beh, una chiamata a help potrebbe far luce.

>>> 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. 

Così sembra che csv.reader aspetta un iteratore di qualche tipo che restituirà una linea, ma stiamo passando una stringa che itera su un char basi che è il motivo per cui il suo carattere di analisi per carattere, un modo per risolvere questo problema sarebbe quello di generare un file temporaneo, ma non abbiamo bisogno di, abbiamo solo bisogno di passare qualsiasi oggetto iterable.

notare quanto segue, che semplicemente divide la stringa in un elenco di righe, prima di essere alimentata al lettore.

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 

questo sembra funzionare.

Si consiglia inoltre di utilizzare csv.DictReader piuttosto utile.

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

fondamentalmente si restituisce un dizionario per ogni riga, utilizzando l'intestazione come la chiave, in questo modo non abbiamo bisogno di tenere traccia dell'ordine, ma invece solo il nome facendo un po 'più facile per noi IE row['Votes'] sembra più leggibile quindi row[4] ...

+0

Dovrei averlo capito da solo. Grazie mille. – foxyNinja7

1

Forse si vuole fiutare il dialetto attraverso l'API CSV:

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

Questo produrrà l'output corretto.

Vedi anche

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

+0

L'originale è in realtà che si sta passando i dati direttamente al lettore() Funzione di costruzione, invece di handle di file. –

3

Questo funziona perfettamente:

import csv 

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

Il primo parametro da csv.reader dovrebbe essere:

qualsiasi oggetto che supporta il protocollo iteratore e restituisce un stringa ogni volta il suo metodo next() viene chiamato

secondo the docs, e si sta passando una stringa, non un oggetto file. Una stringa si comporta come una lista di singoli caratteri, quindi il comportamento che stai osservando.

4

problema semplice: Il csv.reader non si aspettava una stringa per il suo contributo.

Soluzione semplice: Modificare l'input in: data.splitlines().

Il lettore csv si aspetta un iterable che restituisca le righe una alla volta. Una stringa, sfortunatamente, itera un personaggio alla volta. Per risolvere il problema, utilizzare splitlines() per accendere la stringa in una lista di linee:

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