Domanda

I'm using ftplib to create a simple script to push out a file to multiple IP addresses, all set up as FTP servers. I wanted to display progress in the file upload process, but I'm having an issue. I use the callback argument of FTP.storbinary() and it works with something like this:

count = 0
def update(block):
   count2 = str(count + 1)
   print count2

However, if I try to do any arithmetic outside of a str() call, the program hangs. So the following doesn't work:

count = 0
def update(block):
   count += 1
   print count

Even wrapping count in a str() call doesn't work. It just hangs on the first call.

È stato utile?

Soluzione

If you just try calling update yourself, instead of passing it to FTP.storbinary, you'll see the problem immediately:

>>> update('')
UnboundLocalError: local variable 'count' referenced before assignment

If you want to update a global variable, you have to mark it global explicitly:

def update(block):
   global count
   count += 1
   print count

See the FAQ entry Why am I getting an UnboundLocalError when the variable has a value? and the following question What are the rules for local and global variables in Python?, and the docs on global, for more details.


A better way to solve this would be to write a class:

class FtpHandler(object):
    def __init__(self):
        self.count = 0
    def update(self, block):
        self.count += 1
        print self.count

Then, to use it, you construct an instance of the class, and pass a bound method instead of a plain function to the FTP code. For example, instead of this:

ftp = ftplib.FTP(...)
# ...
ftp.storbinary(spam, eggs, callback=update)

… do this:

myhandler = FtpHandler()
ftp = ftplib.FTP(...)
# ...
ftp.storbinary(spam, eggs, callback=myhandler.update)

Altri suggerimenti

It doesn't just hang, it produces an Exception (specifically an UnboundLocalError). You're trying to modify a global variable inside of a function; to do this the variable must be declared global:

count = 0
def update(block):
   global count
   count += 1
   print count

This is almost always a sign of bad design, in your case it would probably be better to use a class with an attribute:

class MyCallbackHandler(object):
    def __init__(self):
        self.count = 0

    def update(self, block):
        self.count += 1
        #... etc.
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top