2

Hi I am trying to create an FTP server and to aid the development I'm using pyftpdlib. What I wanted to do is to do some file operations if a user downloads a specific file but sometimes it raises an exception and I don't really know why.

I wrote my own handler in pyftpdlib after this tutorial: http://code.google.com/p/pyftpdlib/wiki/Tutorial#3.8_-_Event_callbacks

But something goes terribly wrong sometimes when the user downloads the log file (which I intend to do some file operations on) and I don't really understand why. I have another class which basically reads from a configuration file and the error message said it couldn't find FTP Section. But it's strange because I clearly have it in my configuration file and it is working sometimes perfectly.

May this error appear because I have two "Connection" objects? That's the only guess I have, so I would be very glad if someone could explain what's going wrong. Here is my code that's troubled (nevermind the file.name check because that was very recently added):

class ArchiveHandler(ftpserver.FTPHandler):

def on_login(self, username):
    # do something when user login
    pass

def on_logout(self, username):
    # do something when user logs out
    pass


def on_file_sent(self, file):
    "What to do when retrieved the file the class is watching over"
    attr = Connection()
    if attr.getarchive() == 'true':
        t = datetime.now()
    if file.name == "log.log":

            try:
                shutil.copy2(file, attr.getdir() + ".archive/" + str(t.strftime("%Y-%m-%d_%H:%M:%S") + '.log'))
            except OSError:
                print 'Could not copy file'
                raise

        if attr.getremain() == 'false':
                try:
                    os.remove(file)
                except OSError:
                    print 'Could not remove file'
                    raise

The full source: http://pastie.org/3552079

Source of the config-file: http://pastie.org/3552085

EDIT-> (and of course the error):

[root]@85.230.122.159:40659 unhandled exception in instance <pyftpdlib.ftpserver.DTPHandler object at 0xb75f49ec>
Traceback (most recent call last):
  File "/usr/lib/python2.6/asyncore.py", line 84, in write
    obj.handle_write_event()
  File "/usr/lib/python2.6/asyncore.py", line 435, in handle_write_event
    self.handle_write()
  File "/usr/lib/python2.6/asynchat.py", line 174, in handle_write
    self.initiate_send()
  File "/usr/lib/python2.6/asynchat.py", line 215, in initiate_send
    self.handle_close()
  File "/usr/local/lib/python2.6/dist-packages/pyftpdlib/ftpserver.py", line 1232, in handle_close
    self.close()
  File "/usr/local/lib/python2.6/dist-packages/pyftpdlib/ftpserver.py", line 1261, in close
    self.cmd_channel.on_file_sent(filename)
  File "ftp.py", line 87, in on_file_sent
  File "ftp.py", line 12, in __init__
  File "/usr/lib/python2.6/ConfigParser.py", line 311, in get
    raise NoSectionError(section)
NoSectionError: No section: 'FTP Section'
Oleksi
  • 12,947
  • 4
  • 56
  • 80
Ms01
  • 4,420
  • 9
  • 48
  • 80

2 Answers2

3

The problem is in a section you didn't include. It says

  File "ftp.py", line 12, in __init__
  File "/usr/lib/python2.6/ConfigParser.py", line 311, in get
    raise NoSectionError(section)
NoSectionError: No section: 'FTP Section'

So from the first line, we know that whatever is on line 12 of ftp.py is the problem (since everything below that isn't our code, so we assume that it's correct).

Line 12 is this:

self.ip = config.get('FTP Section', 'hostname')

And the error message says "No section: 'FTP Section'".

From this we can assume there's an error in the config file (that it doesn't have a "FTP Section").

Are you pointing at the correct config file? Is it in the same directory that you're running the script from? Being in the same folder as the script will not work, it must be the folder that you run the script from.

I think this is the problem you're having, since according to the documentation:

If none of the named files exist, the ConfigParser instance will contain an empty dataset.

You can confirm this by trying to open the file.

Brendan Long
  • 53,280
  • 21
  • 146
  • 188
  • I'm quite positive I'm using the correct config-file and it's in the same folder as the script is located and are running from. – Ms01 Mar 09 '12 at 00:20
  • I went and tried to open the file and it worked as expected: – Ms01 Mar 09 '12 at 00:27
  • @cubsink And you're running the script from the folder that it's in (not like `python some/path/ftp.py`, just `python ftp.py`)? Try `open`ing the file then using `readfp()`. Also, you could try `print`ing the return value from `read()`. It should print the names of the files it was able to parse. – Brendan Long Mar 09 '12 at 00:32
  • Hmm, I removed the file.name if statement and added the open function and now it's working flawlessly. Maybe I didn't execute the script from the same directory (because I didn't know that 'till now). But I am still unsure if there is something wrong with my code or not. I'm guessing I just executed it wrong before, but shouldn't that give some error when I'm connecting to the server since I'm using the connection class when I'm starting the server? – Ms01 Mar 09 '12 at 00:34
  • brendan: yes at least this time. But I am unsure if I always did that before which could explain why I only got errors sometimes. – Ms01 Mar 09 '12 at 00:36
  • @cubsink - [This question](http://stackoverflow.com/questions/595305/python-path-of-script) explains how to get the path of the current Python file, which you could use to always get the config file in the same folder if you wanted to. – Brendan Long Mar 09 '12 at 03:46
0

The problem in this case was that by reading the file it left the file open.

I changed to this and it's working much better:

config = ConfigParser.RawConfigParser()
    fp = open('config.cfg')
        config.readfp(fp)

And then when I'm finished reading in the constructor I add:

#Close the file
fp.close()

And voila, you can open how many objects of the class you want and it won't show any errors. :)

Ms01
  • 4,420
  • 9
  • 48
  • 80
  • 1
    You should have a look at the [`with`](http://docs.python.org/reference/compound_stmts.html#with) statement, which will handle closing of files automatically for you, even if an exception is while reading the file. – Chris Mar 19 '12 at 12:49