0

I am trying to make a FTP script in Python3.2 that connects to a server and downloads all the contents. While it handles files perfectly, directories seem to make things a bit troubling. I have made it so when it encounters the directory it will set the variable directory to the new directory and hopefully download it's contents. It will exclude an items already completed and if all the contents in directory are in the completed it will back of the directory until it finishes. While the code seems like it would work it doesn't. It seems I can't change directory mid session of a for loop. Here is the code: **Note some variables might be removed later, just want to get a rough draft going here

import os, time, math, ftplib, zipfile, socket ## Just the regular imports... I guess

session = ftplib.FTP("CENSORED.info")
session.login(user="CENSORED",passwd="CENSORED")
dbpath = "/home/CENSORED/Dropbox/CENSORED"

debuglevel=0
session.set_debuglevel(debuglevel)

if session.getwelcome() != "":
        level = 1
    completed = []
    leveldir = {}
    currentdir = session.pwd()
    directory = session.nlst()
    reset = False
    print("CONNECTED")
    print("")

    while level != 0:
        if reset == False:
        level = 0
        reset = True

        try:
            print(directory)


            for file in directory:
                if file not in completed:
                   try:
                    print("Getting",file)
                    savefile = open(os.path.join(dbpath,file), 'wb')
                    session.retrbinary("RETR %s" % file, savefile.write) 
                    completed.append(file)

                   except ftplib.error_perm:
                    level += 1
                    leveldir[level] = currentdir
                    session.cwd(currentdir + file)
                    leveldir[level] = currentdir
                    directory = session.nlst()
                    print(leveldir,level)
                    print(file,"is a Directory! Attempting to enter...")
        if directory in completed:
            level -= 1
            session.cwd(leveldir[level])




    except IOError:
        print("Could Not obtain directory...")

else:
print("")
print("DISCONNECTED")


session.close()
print("")
print("DISCONNECTED")

**Note I can't guarantee that the spacing is correct, it's very hard to tell in Stackoverflow's post editor. For a website about programming I think they should handle code snippets much better than they do.

Here is the error I get in console:

lib is a Directory! Attempting to enter...
Getting minecraft_server.jar
Traceback (most recent call last):
  File "CENSOREDftpbackup.py", line 34, in <module>
    session.retrbinary("RETR %s" % file, savefile.write) 
  File "/usr/local/lib/python3.2/ftplib.py", line 417, in retrbinary
    with self.transfercmd(cmd, rest) as conn:
  File "/usr/local/lib/python3.2/ftplib.py", line 379, in transfercmd
    return self.ntransfercmd(cmd, rest)[0]
  File "/usr/local/lib/python3.2/ftplib.py", line 342, in ntransfercmd
    resp = self.sendcmd(cmd)
  File "/usr/local/lib/python3.2/ftplib.py", line 255, in sendcmd
    return self.getresp()
  File "/usr/local/lib/python3.2/ftplib.py", line 229, in getresp
    raise error_perm(resp)
ftplib.error_perm: 550 Can't open minecraft_server.jar: No such file or directory

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "CENSORED.py", line 40, in <module>
    session.cwd(currentdir + file)
  File "/usr/local/lib/python3.2/ftplib.py", line 556, in cwd
    return self.voidcmd(cmd)
  File "/usr/local/lib/python3.2/ftplib.py", line 260, in voidcmd
    return self.voidresp()
  File "/usr/local/lib/python3.2/ftplib.py", line 234, in voidresp
    resp = self.getresp()
  File "/usr/local/lib/python3.2/ftplib.py", line 229, in getresp
    raise error_perm(resp)
ftplib.error_perm: 550 Can't change directory to /minecraft_server.jar: Not a directory

Thanks!

Clement
  • 367
  • 2
  • 18
  • Copy and paste should work for you. Anyway, there should be some plugin for your preferred web browser that makes things easier. In firefox, I use [It's All Text!](https://addons.mozilla.org/en-US/firefox/addon/its-all-text/). – jcollado Jan 21 '12 at 13:27

2 Answers2

2

I think you should use recursion. I don't know python well enough to show you what it should look like, but here's some pseudo code

startFolder = '/home/nick'

processFolder(startFolder)

def processFolder(folder)
    session.changedir(folder)
    for entry in folder
        if entry isa directory
            processFolder(entry)
        else
            processFile(entry)
    session.changedir('..')

The processFile method should perform the copy or whatever.

I hope that's clear.

nickd
  • 3,951
  • 2
  • 20
  • 24
  • Oh that's a good idea. I'll try it, though I'm still wondering if I can change a variable in a for loop while it's running. Hopefully someone quite fluent in Python can comment as well. Thank you Nickd! – Clement Jan 21 '12 at 13:39
  • Oh, I think I know why I can't do that. The way I tell if it is a directory is if it returns an error 550, and I only get that after trying to download the file. Maybe I can break it? Thanks thought @nickd – Clement Jan 21 '12 at 13:49
2

No, you can't in general change the thing you are iterating over, because there is behind-the-scenes work that Python does when in a for loop that doesn't get updated when you rebind the variable.

Recursively walking a directory tree on an ftp server is a solved problem; you can use ftplib.

Community
  • 1
  • 1
Katriel
  • 120,462
  • 19
  • 136
  • 170
  • Okay, I don't exactly see how it is solved and then saying I can use ftplib. I kind of need to stick to default libraries, but thanks for the answer about for loops! – Clement Jan 21 '12 at 14:00
  • Sorry. My point was that you shouldn't have to write this code, because somebody else has already done it. I think @nickd's answer is neat. – Katriel Jan 21 '12 at 18:42