2012-08-27 12 views
13

Estoy intentando recorrer un archivo delimitado por tabuladores de resultados de elección usando Python. El siguiente código no funciona, pero cuando uso un archivo local con los mismos resultados (la línea comentada), funciona como se esperaba.Archivo delimitado por tabuladores que utiliza csv.reader que no delimita donde lo espero

Lo único que puedo pensar es en algunos encabezados o tipo de contenido que necesito para pasar la url, pero no puedo resolverlo.

¿Por qué sucede esto?

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 

Resultados: en

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

Respuesta

29

¿qué ocurre, bueno, una llamada a help puede arrojar algo de luz.

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

lo que parece que csv.reader espera un iterador de algún tipo que devolverá una línea, pero estamos pasando una cadena que itera sobre una base de char por lo que su carácter de análisis por carácter, una manera de solucionar este problema sería generar un archivo temporal, pero no es necesario, solo tenemos que pasar cualquier objeto iterativo.

tenga en cuenta lo siguiente, que simplemente divide la cadena en una lista de líneas, antes de alimentar al lector.

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 

esto parece funcionar.

También recomiendo usar csv.DictReader es bastante útil.

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

básicamente se devuelve un diccionario para cada fila, utilizando la cabecera como la clave, de esta manera no es necesario hacer un seguimiento de la orden, pero en cambio sólo el nombre de hacer un poco más fácil para nosotros es decir row['Votes'] parece más legible luego row[4] ...

+0

debería haberme dado cuenta por mi cuenta. Muchas gracias. – foxyNinja7

1

Tal vez quieren oler el dialecto a través de la API de CSV:

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

Esto producirá la salida correcta.

Consulte también

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

+0

El original es en realidad que se está de paso los datos directamente al constructor lector() en lugar de identificador de archivo. –

3

Esto funciona perfectamente:

import csv 

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

El primer parámetro a csv.reader debe ser:

cualquier objeto que soporta el protocolo iterador y devuelve una cadena cada vez es siguiente método() se llama

según the docs, y se le pasa una cadena, no un objeto de archivo. Una cadena se comporta como una lista de caracteres individuales, por lo tanto, el comportamiento que está observando.

4

problema simple: El csv.reader no esperaba una cadena para su entrada.

Solución simple: Cambie la entrada a: data.splitlines().

El lector de csv espera un iterable que devuelva las líneas de a una por vez. Desafortunadamente, una cadena itera un carácter a la vez. Para resolver el problema, utilice splitlines() para encender la cadena en una lista de líneas:

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