While writing a function that will show a progress bar while downloading a list of files from an ftp server I ended up with some strange script:
with ftplib.FTP(...) as ftp:
files = list(ftp.mlsd(path=remote_dir_path))
total_size = sum(int(f[1]['size']) for f in files)
total_done = 0
current_done = 0
current_size = 0
def callback(chunk):
global current_done
global total_done
global current_size
global total_size
trg_file.write(chunk) # how? why it knows what is `trg_file`?
current_done += len(chunk)
total_done += len(chunk)
print_progressbar(current_done,total_done,...)
for file in files:
current_done = 0
current_size = int(file[1]['size'])
with open(file[0],'wb') as trg_file:
ftp.retrbinary('RETR %s/%s'%(remote_dir_path,file[0]),callback)
I had to write global
in callback
function so that python does not complain about it. BUT it knew what is trg_file
no problem?!?!?!
Trying to understand I wrote a small test:
def callback():
print(foo)
def main():
foo = 'FOOOO'
callback()
main()
It failed as expected.
I get why the second script does not work. Intuition says that the first should not work too. But it works. Can somebody please explain why?
EDIT:
The question is not about global
itself, but about with ... as ...
block and scope (scope of ... as variable
variable)