У меня есть большой CSV-файл клиента, которым можно поделиться через URL-адрес для загрузки, и я хочу загрузить его построчно, или по байтам, и я хочу ограничить только 10 записями.
У меня есть следующий код, который загрузит файл, но я хочу здесь загрузить только первые 10 записей из файла, мне не нужен полный файл.
#!/usr/bin/env python
import requests
from contextlib import closing
import csv
url = "https://example.com.au/catalog/food-catalog.csv"
with closing(requests.get(url, stream=True)) as r:
f = (line.decode('utf-8') for line in r.iter_lines())
reader = csv.reader(f, delimiter=',', quotechar='"')
for row in reader:
print(row)
Я мало что знаю о contextlib
, как он будет работать с with
в Python.
Может ли кто-нибудь помочь мне здесь, это было бы действительно полезно, и заранее спасибо.
Проблема не столько в contextlib
, сколько в генераторах. Когда ваш блок with
завершится, соединение будет закрыто, довольно просто.
Часть, которая фактически выполняет загрузку, - это for row in reader:
, поскольку reader
обернут вокруг f
, который является ленивый генератор. Каждая итерация цикла будет фактически читать строку из потока, возможно, с некоторой внутренней буферизацией Python.
Ключ тогда - остановить цикл после 10 строк. Есть несколько простых способов сделать это:
for count, row in enumerate(reader, start=1):
print(row)
if count == 10:
break
Или
from itertools import islice
...
for row in islice(reader, 0, 10):
print(row)
Вы можете использовать islice из itertools, чтобы решить вашу проблему.
#!/usr/bin/env python
import csv
import requests
from contextlib import closing
from itertools import islice
url = "https://example.com.au/catalog/food-catalog.csv"
with closing(requests.get(url, stream=True)) as r:
f = (line.decode('utf-8') for line in r.iter_lines())
reader = csv.reader(f, delimiter=',', quotechar='"')
rows = list(islice(f, 10))
print(rows)
Вы можете обобщить идею, создав генератор, который будет выдавать следующие n строк при каждом вызове. Рецепт grouper
из модуля itertools
полезен для подобных вещей.
import requests
import itertools
import csv
import contextlib
def grouper(iterable, n, fillvalue=None):
"Collect data into fixed-length chunks or blocks"
# grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx"
args = [iter(iterable)] * n
return itertools.zip_longest(*args, fillvalue=fillvalue)
def stream_csv_download(chunk_size):
url = 'https://www.stats.govt.nz/assets/Uploads/Annual-enterprise-survey/Annual-enterprise-survey-2017-financial-year-provisional/Download-data/annual-enterprise-survey-2017-financial-year-provisional-csv.csv'
with contextlib.closing(requests.get(url, stream=True)) as stream:
lines = (line.decode('utf-8') for line in stream.iter_lines(chunk_size))
reader = csv.reader(lines, delimiter=',', quotechar='"')
chunker = grouper(reader, chunk_size, None)
while True:
try:
yield [line for line in next(chunker)]
except StopIteration:
return
csv_file = stream_csv_download(10)
Это определенно буферизует некоторый объем данных, поскольку вызовы быстрые, но я не думаю, что он загружает весь файл. Придется тестировать с большим файлом.
Извините, я написал это на Python 2 и попытался преобразовать в 3, я думаю, что если вы используете contextlib.closing в операторе with, он будет работать.
Панды тоже могут быть подходом:
import pandas as pd
#create a datafram from your original csv, with "," as your separator
#and limiting the read to the first 10 rows
#here, I also configured it to also read it as UTF-8 encoded
your_csv = pd.read_csv("https://example.com.au/catalog/food-catalog.csv", sep = ',', nrows = 10, encoding = 'utf-8')
#You can now print it:
print(your_csv)
#And even save it:
your_csv.to_csv(filePath, sep = ',', encoding = 'utf-8')
helena работает нормально, за исключением случаев, когда я пытаюсь сохранить в другой файл, получаю эту ошибку UnicodeEncodeError: кодек 'ascii' не может кодировать символ u '\ xe7' в позиции 1: порядковый номер не в диапазоне (128)
Попробуй это сейчас. Я исправил кодировку как на read_csv
, так и на to_csv
получение ошибки для URL-адреса клиента, как показано ниже клиент: [email protected]/feeds/client/… httplib.InvalidURL: нечисловой порт: '[email protected]'
Похоже на ошибку при доступе к описанному вами URL. Какая строка возвращает ошибку?
Отслеживание (последний вызов последним): файл "pandas_file.py", строка 7, в <module> "клиент: [email protected]/feeds/client/…", sep = ',', nrows = 10, encoding = 'utf-8') Файл "/ usr / local /lib/python2.7/dist-packages/pandas/io/parsers.py ", строка 678, в parser_f return _read (filepath_or_buffer, kwds) File" /usr/local/lib/python2.7/dist-packages/ pandas / io / parsers.py ", строка 424, в _read
Есть две возможности: во-первых, что-то не так с вашей конфигурацией URL-адреса; во-вторых, код, который я вам дал, находится на Python 3.x, и, очевидно, вы используете 2.7 (хотя, скорее всего, эта вторая возможность не является проблемой)
с помощью requests.get (url, stream = True) в качестве потока: AttributeError: выход получает эту ошибку