J'essaie de parcourir un fichier délimité par des tabulations des résultats des élections à l'aide de Python. Le code suivant ne fonctionne pas, mais lorsque j'utilise un fichier local avec les mêmes résultats (la ligne commentée), il fonctionne comme prévu.
La seule chose à laquelle je peux penser est quelques en-têtes ou type de contenu dont j'ai besoin pour passer l'URL, mais je ne peux pas le comprendre.
Pourquoi cela arrive-t-il?
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
Résulte en:
...
['', '']
['', '']
['2']
['3']
['1']
['1']
['8']
['', '']
['D']
['a']
['v']
['i']
['d']
[' ']
['F']
['r']
['a']
['z']
['i']
['e']
['', '']
...
donc ce qui se passe, eh bien, un appel à help
peut nous éclairer.
>>> 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.
il semble donc que csv.reader
attend un itérateur d'une sorte qui retournera une ligne, mais nous passons une chaîne qui itère sur une base de caractères, c'est pourquoi son analyse caractère par caractère, une façon de résoudre ce problème serait pour générer un fichier temporaire, mais nous n'en avons pas besoin, nous avons juste besoin de passer tout objet itérable.
notez ce qui suit, qui divise simplement la chaîne en une liste de lignes, avant de la transmettre au lecteur.
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
cela semble fonctionner.
Je recommande également d'utiliser csv.DictReader
, C'est très 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'}
fondamentalement, il renvoie un dictionnaire pour chaque ligne, en utilisant l'en-tête comme clé, de cette façon, nous n'avons pas besoin de garder une trace de la commande, mais à la place, le nom nous facilite un peu, c'est-à-dire que row['Votes']
semble plus lisible. alors row[4]
...
Problème simple: Le csv.reader ne s'attendait pas à une chaîne pour son entrée.
Solution simple: Modifiez l'entrée en: data.splitlines()
.
Le lecteur csv attend un itérable qui renvoie les lignes une à la fois. Une chaîne, malheureusement, itère un caractère à la fois. Pour résoudre le problème, utilisez splitlines () pour transformer la chaîne en une liste de lignes:
reader = csv.reader(data.splitlines(), delimiter='\t')
for row in reader:
print row
Cela fonctionne parfaitement:
import csv
reader = csv.reader(open('./MediaResults.txt'),
delimiter='\t')
for row in reader:
print row
Le premier paramètre à csv.reader
devrait être:
tout objet qui prend en charge le protocole itérateur et renvoie une chaîne chaque fois que sa méthode suivante () est appelée
selon les docs , et vous passez une chaîne, pas un objet fichier. Une chaîne se comporte comme une liste de caractères uniques, d'où le comportement que vous observez.
Vous souhaitez peut-être flairer le dialecte via l'API csv:
csvfile = open("example.csv", "rb")
dialect = csv.Sniffer().sniff(csvfile.read(1024))
csvfile.seek(0)
reader = csv.reader(csvfile, dialect)
Cela produira la sortie correcte.
Voir également