Ошибка Python: итератор должен возвращать строки, а не байты (вы открыли файл в текстовом режиме?) [Duplicate]

C # Version ... обратите внимание, что я получаю строки цвета в этом формате # FF12AE34, и вам нужно вырезать #FF.

    private string GetSmartShadeColorByBase(string s, float percent)
    {
        if (string.IsNullOrEmpty(s))
            return "";
        var r = s.Substring(3, 2);
        int rInt = int.Parse(r, NumberStyles.HexNumber);
        var g = s.Substring(5, 2);
        int gInt = int.Parse(g, NumberStyles.HexNumber);
        var b = s.Substring(7, 2);
        int bInt = int.Parse(b, NumberStyles.HexNumber);

        var t = percent < 0 ? 0 : 255;
        var p = percent < 0 ? percent*-1 : percent;

        int newR = Convert.ToInt32(Math.Round((t - rInt) * p) + rInt);
        var newG = Convert.ToInt32(Math.Round((t - gInt) * p) + gInt);
        var newB = Convert.ToInt32(Math.Round((t - bInt) * p) + bInt);

        return String.Format("#{0:X2}{1:X2}{2:X2}", newR, newG, newB);
    }
24
задан Chris 19 September 2013 в 15:09
поделиться

3 ответа

Проблема связана с возвратом байтов urllib. В качестве доказательства вы можете попробовать загрузить файл csv с помощью своего браузера и открыть его как обычный файл, и проблема исчезла.

Аналогичная проблема была рассмотрена здесь здесь .

Можно решить декодирование байтов в строки с соответствующим кодированием. Например:

import csv
import urllib.request

url = "ftp://ftp.ncbi.nlm.nih.gov/pub/pmc/file_list.csv"
ftpstream = urllib.request.urlopen(url)
csvfile = csv.reader(ftpstream.read().decode('utf-8'))  # with the appropriate encoding 
data = [row for row in csvfile]

Последняя строка также может быть: data = list(csvfile), которую легче читать.

Кстати, поскольку файл csv очень велик, может замедляться и потреблять память. Возможно, было бы предпочтительнее использовать генератор.

EDIT: Использование кодеков, предложенных Стивеном Румбальским, поэтому нет необходимости читать весь файл для декодирования.

import csv
import urllib.request
import codecs

url = "ftp://ftp.ncbi.nlm.nih.gov/pub/pmc/file_list.csv"
ftpstream = urllib.request.urlopen(url)
csvfile = csv.reader(codecs.iterdecode(ftpstream, 'utf-8'))
for line in csvfile:
    print(line)  # do something with line

Обратите внимание, что список не создается по той же причине.

34
ответ дан Community 1 September 2018 в 09:43
поделиться

urlopen вернет экземпляр urllib.response.addinfourl для запроса ftp.

Для объяснения URL-адресов, файлов и данных URL-адресов, обработанных устаревшими классами URLopener и FancyURLopener, эта функция возвращает объект urllib.response.addinfourl, который может работать как менеджер контекста ...

>>> urllib2.urlopen(url)
<addinfourl at 48868168L whose fp = <addclosehook at 48777416L whose fp = <socket._fileobject object at 0x0000000002E52B88>>>

На этом этапе ftpstream представляет собой файл , такой как объект, использование .read() вернет содержимое, однако csv.reader требует итерации в этом случае:

Определение генератора так:

def to_lines(f):
    line = f.readline()
    while line:
        yield line
        line = f.readline()

Мы можем создать наш csv-ридер так:

reader = csv.reader(to_lines(ftps))

И с URL

url = "http://pic.dhe.ibm.com/infocenter/tivihelp/v41r1/topic/com.ibm.ismsaas.doc/reference/CIsImportMinimumSample.csv"

Код:

for row in reader: print row

Печатает

>>> 
['simpleci']
['SCI.APPSERVER']
['SRM_SaaS_ES', 'MXCIImport', 'AddChange', 'EN']
['CI_CINUM']
['unique_identifier1']
['unique_identifier2']
-1
ответ дан HennyH 1 September 2018 в 09:43
поделиться

Несмотря на то, что уже есть принятый ответ, я думал, что добавлю к телу знания, показывая, как я достиг чего-то подобного, используя пакет requests (который иногда рассматривается как альтернатива urlib.request).

Основа использования codecs.itercode() для решения исходной задачи по-прежнему такая же, как в принятом ответе .

import codecs
from contextlib import closing
import csv
import requests

url = "ftp://ftp.ncbi.nlm.nih.gov/pub/pmc/file_list.csv"

with closing(requests.get(url, stream=True)) as r:
    reader = csv.reader(codecs.iterdecode(r.iter_lines(), 'utf-8'))
    for row in reader:
        print row   

Здесь мы также видим использование потоковой передачи , предоставляемой через пакет requests, чтобы избежать необходимости сначала загружать весь файл по сети в память (что может потребоваться много времени, если файл большой).

Я думал, что это может быть полезно, поскольку это помогло мне, поскольку я использовал requests, а не urllib.request в Python 3.6.

Некоторые из идей (например, с использованием closing()) выбираются из этой аналогичной записи

4
ответ дан Michal Skop 1 September 2018 в 09:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: