سؤال

I am trying to download a .zip file from a FTP server and I keep getting this error:

File "C:/filename.py", line 37, in handleDownload
file.write(block)
TypeError: descriptor 'write' requires a 'file' object but received a 'str'

Here's my code (borrowed from http://postneo.com/stories/2003/01/01/beyondTheBasicPythonFtplibExample.html):

def handleDownload(block):
    file.write(block)
    print ".",

ftp = FTP('ftp.godaddy.com') # connect to host
ftp.login("auctions") # login to the auctions directory
print ftp.retrlines("LIST")
filename = 'auction_end_tomorrow.xml.zip'
file = open(filename, 'wb')
ftp.retrbinary('RETR ' + filename, handleDownload)
file.close()
ftp.close()
هل كانت مفيدة؟

المحلول

I can't reproduce this myself, but I have an idea of what's happening -- I'm just not sure how it's happening. Hopefully someone can chime in. Note that file isn't passed through to handleDownload, and file is also the name of a builtin type. If file were left as the builtin, then you'd get exactly this error:

>>> file
<type 'file'>
>>> file.write("3")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: descriptor 'write' requires a 'file' object but received a 'str'

So I think some of the problem is a confusion between file, the built-in, and file, the opened file itself. (Probably using a name other than "file" is a good idea here.) Anyway, if you simply use

ftp.retrbinary('RETR ' + filename, file.write)

and ignore the handleDownload function entirely, it should work. Alternatively, if you wanted to keep the dots printing every block, you could be a little fancier, and write something like

def handleDownloadMaker(openfile):
    def handleDownload(block):
        openfile.write(block)
        print ".",
    return handleDownload

which is a function which returns a function that points at the right file. After that,

ftp.retrbinary('RETR' + filename, handleDownloadMaker(file))

should work too.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top