Подтвердить что ты не робот

Файл с разделителями-табуляторами с использованием csv.reader, не ограничивающий, где я ожидаю

Я пытаюсь прокрутить файл с разделителями табуляции результатов выборов, используя 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']
['', '']
...
4b9b3361

Ответ 1

так что происходит, ну, вызов 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 ожидает итератора какого-либо типа, который вернет строку, но мы передаем строку, которая итерации на основе char, поэтому его синтаксический анализ по символу, один из способов исправить это было бы создание временного файла, но нам не нужно, нам просто нужно передать любой итерируемый объект.

обратите внимание на следующее, которое просто разбивает строку на список строк, прежде чем ее подают в считыватель.

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

Ответ 2

Простая проблема: csv.reader не ожидал ввода строки.

Простое решение: Измените ввод на: data.splitlines().

Считыватель csv ожидает итерабельность, которая возвращает строки по одному. Строка, к сожалению, повторяет характер за раз. Чтобы решить проблему, используйте splitlines(), чтобы превратить строку в список строк:

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

Ответ 3

Это отлично работает:

import csv

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

Первым параметром csv.reader должен быть:

любой объект, который поддерживает протокол итератора и возвращает строку каждый раз его следующий() метод называется

согласно документы, и вы передаете строку, а не файл. Строка ведет себя как список одиночных символов, следовательно, поведение, которое вы наблюдаете.

Ответ 4

Возможно, вы хотите понюхать диалект через API csv:

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