Подтвердите, что Python 2.6 ftplib не поддерживает имена файлов Unicode?Альтернативы? - PullRequest
2 голосов
/ 25 июня 2010

Может ли кто-нибудь подтвердить, что Python 2.6 ftplib НЕ поддерживает имена файлов Unicode? Или имена файлов Unicode должны быть специально закодированы для использования с модулем ftplib?

Следующий обмен электронной почтой подтверждает мой вывод о том, что модуль ftplib поддерживает только имена файлов ASCII.

Должен ли ftplib использовать UTF-8 вместо кодировки latin-1? http://mail.python.org/pipermail/python-dev/2009-January/085408.html

Есть ли какие-либо рекомендации для стороннего модуля Python FTP, который поддерживает имена файлов Unicode? Я погуглил этот вопрос безуспешно [1], [2].

Официальная документация Python не содержит имен файлов Unicode [3].

Спасибо, Malcolm

[1] ftputil оборачивает ftplib и наследует очевидную поддержку только ASCII ftplib?

[2] Библиотека Paramiko SFTP поддерживает имена файлов Unicode, однако я специально искал поддержку ftp (против sftp) относительно нашего текущего проекта.

[3] http://docs.python.org/library/ftplib.html

Временное решение:

Методы encodings.idna.ToASCII и .ToUnicode могут использоваться для преобразования имен путей Unicode в формат ASCII. Если вы оберните все свои удаленные пути и выходные данные методов dir / nlst с помощью этих функций, то вы сможете создать способ сохранения имен путей Unicode с помощью стандартного ftplib (а также сохранения имен файлов Unicode в файловых системах, которые не поддержка Unicode путей). Недостатком этого метода является то, что другие процессы на сервере также должны будут использовать encodings.idna при обращении к файлам, которые вы загружаете на сервер. Кстати, я понимаю, что это злоупотребление библиотекой encodings.idna.

Спасибо, Питер и Боб, за ваши комментарии, которые я нашел очень полезными.

Ответы [ 5 ]

7 голосов
/ 25 июня 2010

ftplib не знает юникода вообще.Он предназначен для передачи байтовых строк для имен файлов, и он будет возвращать байтовые строки при запросе списка каталогов.Это точные строки байтов, переданные / возвращенные с сервера.

Если вы передадите строку Unicode в ftplib в Python 2.x, он будет приведен к байтам, когдаотправлено в базовый объект сокета.Это принуждение использует кодировку Python по умолчанию, т.е.US-ASCII для безопасности, с исключениями, сгенерированными для не-ASCII символов.

Сообщение Python-dev, с которым вы связались, говорит о ftplib в Python 3.x, где строки по умолчанию являются Unicode.Это оставляет такие модули, как ftplib, в сложной ситуации, потому что, хотя они теперь используют строки Unicode на своем внешнем интерфейсе, фактический протокол позади него основан на байтах.Следовательно, необходим дополнительный уровень кодирования / декодирования, и без явного вмешательства для определения того, какая кодировка используется, есть справедливое изменение, которое он выберет неправильно.

ftplib в 3.x selectedпо умолчанию ISO-8859-1, чтобы сохранить каждый байт как символ внутри строки Unicode.К сожалению, это даст неожиданные результаты в общем случае, когда целевой сервер использует параметры сортировки UTF-8 для имен файлов (независимо от того, знает ли сам демон FTP, что имена файлов являются UTF-8, чего обычно нет).В ряде случаев, подобных этому, стандартные библиотеки Python были жестоко взломаны на строки Unicode с негативными последствиями;Аккумуляторы Python 3, входящие в комплект, по-прежнему протекают едкая жидкость IMO.

2 голосов
/ 25 июня 2010

Лично я бы больше беспокоился о том, что находится на другой стороне ftp-соединения, чем поддержка библиотеки.FTP является хрупким протоколом в лучшие времена, не пытаясь творчески подходить к именам файлов.

из RFC 959:

     Pathname is defined to be the character string which must be
     input to a file system by a user in order to identify a file.
     Pathname normally contains device and/or directory names, and
     file name specification.  FTP does not yet specify a standard
     pathname convention.  Each user must follow the file naming
     conventions of the file systems involved in the transfer.

Для меня это означает, что имена файлов должны соответствовать самым низким общимзнаменатель.Поскольку в настоящее время количество серверов DOS, мэйнфреймов Vax и IBM незначительно, и есть вероятность, что вы окажетесь в коробке с Windows или Unix, поэтому общий знаменатель довольно высок, но, по-видимому, делаются предположения о том, какую кодовую страницу хочет принять удаленный сайт.я довольно рискованно.

0 голосов
/ 30 сентября 2013

Мы получили имена файлов в кодировке UTF8, работающие с библиотекой FTP Python 2.7.

Примечание 1: Вот фон, который легко объясняет UTF8 и Unicode: https://code.google.com/p/iqbox-ftp/wiki/ProgrammingGuide_UnicodeVsAscii

Примечание 2: Вы можете взглянуть на библиотеки AGPL, которые мы используем для IQBox.Вы можете использовать их (или их части), и они поддерживают UTF8 через FTP.Посмотрите на filetransfer_abc.py

Вам необходимо добавить код в (1) Определите, поддерживает ли сервер UTF8, и (2) закодируйте строку Python Юникода в формате UTF8.(3) (Полный код не отображается, поскольку каждый получает списки файлов по-разному). Когда вы получаете списки файлов, вам также необходимо использовать if UTF8_support: name = name.decode('utf-8')

# PART (1): DETERMINE IF SERVER HAS UTF8 SUPPORT:
# Get FTP features:
    try:
    features_string_ftp = ftp.sendcmd('FEAT')
    print features_string_ftp

    # Determine UTF8 support:
    if 'UTF8' in features_string_ftp.upper():
        print "FTP>> Server supports international characters (UTF8)"
        UTF8_support = True
    else:
        print "FTP>> Server does NOT support international (non-ASCII) characters."
        UTF8_support = False
    except:
    print "FTP>> Could not get list of features using FEAT command."
    print "FTP>> Server does NOT support international (non-ASCII) characters."
    UTF8_support = False


# Part (2): Encode FTP commands needed to be sent using UTF8 encoding, if it's supported.
    def sendFTPcommand(ftp, command_string, UTF8_support):
    # Needed for UTF8 international file names etc.
    c = None
    if UTF8_support:
        c = command_string.encode('utf-8')
    else:
        c = command_string

    # TODO: Add try-catch here and connection error retries.
    return ftp.sendcmd(c)

    # If you just want to get a string with the UTF8 command and send it yourself, then use this:
       def encodeFTPcommand(self, command_string. UTF8_support):
        # Needed for UTF8 international file names etc.
        c = None
        if UTF8_support:
            c = command_string.encode('utf-8')
        else:
            c = command_string  
        return c
0 голосов
/ 21 мая 2012

Может ли кто-нибудь подтвердить, что Python 2.6 ftplib НЕ поддерживает имена файлов Unicode?

Он не делает.

Если ftplib использовать UTF-8 вместо Latin-1 кодировку?

Это спорно.UTF-8 является предпочтительной кодировкой в ​​соответствии с RFC-2640 , но latin-1 обычно более удобен для неправильной реализации (на сервере или на клиенте).Если сервер включает «UTF8» как часть ответа FEAT, то вам следует окончательно использовать UTF8.

 >>> utf8_server = 'UTF8' in ftp.sendcmd('FEAT')

Для поддержки юникода в python 2.x вы можете принять следующую версию ftpdlib с исправлением обезьян:

class UnicodeFTP(ftplib.FTP):
    """A ftplib.FTP subclass supporting unicode file names as 
   described by RFC-2640."""

    def putline(self, line):
        line = line + '\r\n'
        if isinstance(line, unicode):
            line = line.encode('utf8')
        self.sock.sendall(line)

... и передавать строки Unicode при использовании оставшегося API, как в:

>>> ftp = UnicodeFTP(host='ftp.site.com', user='foo', passwd='bar')
>>> ftp.delete(u'somefile')
0 голосов
/ 06 января 2011

Чтобы обойти это, я использовал следующий код

ftp.storbinary("STOR " + target_name.encode( "utf-8" ), open(file_name, 'rb'))

Это предполагает, что FTP-сервер поддерживает RFC 2640 http://www.ietf.org/rfc/rfc2640.txt, который допускает имена файлов utf-8.В моем случае я использовал сервер SwiFTP для Android, и он успешно передает файлы с правильными именами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...