«IOError: [ошибка ftp без ошибок] 200 Введите значение I» при установке lxml из исходного кода

#python #lxml #urllib #setup.py #ftplib

#python #lxml #urllib #setup.py #ftplib

Вопрос:

Это моя ошибка:

 C:WINDOWSsystem32>pip install scrapy --upgrade

Requirement already up-to-date: scrapy in c:python27libsite-packagesscrapy-1.2.0-py2.7.egg
Requirement already up-to-date: Twisted>=10.0.0 in c:python27libsite-packages (from scrapy)
Requirement already up-to-date: w3lib>=1.15.0 in c:python27libsite-packages (from scrapy)
Requirement already up-to-date: queuelib in c:python27libsite-packages (from scrapy)

Collecting lxml (from scrapy)

  Using cached lxml-3.6.4.tar.gz

    Complete output from command python setup.py egg_info:
    Building lxml version 3.6.4.
    Retrieving "ftp://ftp.zlatkovic.com/pub/libxml/libxslt-1.1.26.win32.zip" to "libslibxslt-1.1.26.win32.zip"
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "c:usersthezmappdatalocaltemppip-build-y3m3fllxmlsetup.py", line 233, in <module>
        **setup_extra_options()
      File "c:usersthezmappdatalocaltemppip-build-y3m3fllxmlsetup.py", line 144, in setup_extra_options
        STATIC_CFLAGS, STATIC_BINARIES)
      File "setupinfo.py", line 55, in ext_modules
        OPTION_DOWNLOAD_DIR, static_include_dirs, static_library_dirs)
      File "buildlibxml.py", line 95, in get_prebuilt_libxml2xslt
        libs = download_and_extract_zlatkovic_binaries(download_dir)
      File "buildlibxml.py", line 55, in download_and_extract_zlatkovic_binaries
        urlretrieve(srcfile, destfile)
      File "c:python27liburllib.py", line 98, in urlretrieve
        return opener.retrieve(url, filename, reporthook, data)
      File "c:python27liburllib.py", line 245, in retrieve
        fp = self.open(url, data)
      File "c:python27liburllib.py", line 213, in open
        return getattr(self, name)(url)
      File "c:python27liburllib.py", line 558, in open_ftp
        (fp, retrlen) = self.ftpcache[key].retrfile(file, type)
      File "c:python27liburllib.py", line 906, in retrfile
        conn, retrlen = self.ftp.ntransfercmd(cmd)
      File "c:python27libftplib.py", line 334, in ntransfercmd
        host, port = self.makepasv()
      File "c:python27libftplib.py", line 312, in makepasv
        host, port = parse227(self.sendcmd('PASV'))
      File "c:python27libftplib.py", line 830, in parse227
        raise error_reply, resp
    IOError: [Errno ftp error] 200 Type set to I

    ----------------------------------------
Command "python setup.py egg_info" failed with error code 1 in c:usersthezmappdatalocaltemppip-build-y3m3fllxml
  

Как мне это исправить?

Комментарии:

1. [Errno ftp error] 200 Type set to I кажется, есть проблема с FTP-сервером. Может быть, попробуйте завтра. Или попробуйте загрузить ftp://ftp.zlatkovic.com/pub/libxml/libxslt-1.1.26.win32.zip и установить вручную.

Ответ №1:

Это связано с ошибкой в ftplib и / или urllib : FTP-ответ 226 игнорируется, в результате чего клиент неправильно сопоставляет дальнейшие входящие ответы с исходящими командами.

Я немного покопался и пришел к выводу, что urllib это не может быть полностью исправлено, ftplib как сейчас. Вы можете использовать следующий патч urllib.py , чтобы исправить эту конкретную проблему (разница для Python 2.7.12 ):

 --- a/urllib.py Sat Jun 25 22:46:20 2016
    b/urllib.py Sat Dec 10 00:20:48 2016
@@ -927,7  927,7 @@
         self.busy = 1
         ftpobj = addclosehook(conn.makefile('rb'), self.file_close)
         self.refcount  = 1
-        conn.close()
         #conn.close()
         # Pass back both a suitably decorated object and a retrieval length
         return (ftpobj, retrlen)

@@ -940,7  940,14 @@
             self.real_close()

     def file_close(self):
         import ftplib
         self.endtransfer()
         #Process the 226 transfer complete response
         try:
             self.ftp.voidresp()
         except ftplib.error_temp as msg:
             # transfer is aborted by urllib when some other exception has happened
             if msg.args[0][:3] != '426': raise
         self.refcount -= 1
         if self.refcount <= 0 and not self.keepalive:
             self.real_close()
@@ -990,15  997,13 @@
         self.hookargs = hookargs

     def close(self):
-        try:
-            closehook = self.closehook
-            hookargs = self.hookargs
-            if closehook:
-                self.closehook = None
-                self.hookargs = None
-                closehook(*hookargs)
-        finally:
-            addbase.close(self)
         addbase.close(self)
         closehook = self.closehook
         hookargs = self.hookargs
         if closehook:
             self.closehook = None
             self.hookargs = None
             closehook(*hookargs)


 class addinfo(addbase):
  

Комментарии:

1. извините, но у меня это не сработало, вместо этого я использую urllib2.

2. @Statham это означает, что у вас проблема, отличная от той, которая изложена в этом вопросе. Задайте его как другой.

3. спасибо @ivan_pozdeev, у меня это сработало 🙂 Я только не включил фрагмент для def close(self):

4. @IgordeLorenzi IIRC close часть предназначена для правильного действия, когда соединение передачи было прервано urllib (например, не удается открыть локальный файл).