Getting EOFError along with exceptions when using ftplib

bdeniker picture bdeniker · Jul 25, 2011 · Viewed 7.4k times · Source

I'm looking into using ftplib (and possibly ftputil) for doing some automated FTP file syncing. I have a couple of servers to test this against at the moment, but, whilst I'm having a successful conversation with both servers, I get EOFError-s with each error reply. For example: if I try to log in with an incorrect user/pass, I will get the 530 response with everything... but I also get an EOFError; if I login with a correct user/pass or try to dir() after doing so etc., I get no EOFError.

It seems to only appear with error messages. I strongly suspect this may be caused by the servers rather than python: I've not found any mention of this issue elsewhere. I, however, have very little control over the server setup.

I'm asking for ideas:

  • Do you know what could be causing the error in the first place?
  • If it's server-side, could you be more specific? I won't know if I'll be able to do anything about it until I know what it is...
  • How do you think I should handle this? I guess I could add an except EOFError: pass before each time I handle an exception, but if you have better/neater ideas I would love to hear them.

Thanks!

Answer

agf picture agf · Jul 25, 2011

The servers are sending EOF to tell you that they've terminated the connection.

You should treat this no differently than any other disconnection event, except that obviously you need to handle it with except EOFError.

See the source, from http://svn.python.org/view/python/trunk/Lib/ftplib.py?view=markup

# Internal: return one line from the server, stripping CRLF.
# Raise EOFError if the connection is closed
182     def getline(self):
183         line = self.file.readline()
184         if self.debugging > 1:
185             print '*get*', self.sanitize(line)
186         if not line: raise EOFError
187         if line[-2:] == CRLF: line = line[:-2]
188         elif line[-1:] in CRLF: line = line[:-1]
189         return line

EOFError is only raised when readline() on the connection returns a blank line, which the comment indicates is a disconnection event.

Edit in re your comment:

The server doesn't send an empty line. readline() returns everything up to the next \n or \r or \r\n or all of the abouve depending on how it's configured. In this case, there is nothing to read because the end of the file has been reached. This causes readline() to return a blank line, it doesn't mean a blank line has been read. If a blank line had been read, readline() would return the character that ended the line (\n or \r or \n\r).

If you don't get the exception when using FTPUtil, that is because it handles it internally.