Discussion:
ftplib - uploading files using transfercmd?
Stewart Midwinter
2004-03-19 14:24:13 UTC
Permalink
The first file uploads just fine, but on the second file I'm
consistently seeing a weird problem where the response to the PORT
command (sent by self.makeport()) comes *after* the STOR command is
sent.
Kevin, when you make a socket connection to the server, are you used
blocking or non-blocking? A blocking connection won't proceed until
it gets a response, while the non-blocking will - and perhaps your
problem lies there. your 2nd command gets a response before the first
one comes back.

Does indeed your problem only happen at the beginning, or can it
happen anywhere in your list of files?

S
Kevin Ollivier
2004-03-22 23:05:48 UTC
Permalink
OK, I finally figured out how to fix my problems with the FTP commands
being issued in the wrong order - after I've finished uploading the
file, I have to call ftplib.voidresp().

Is it possible to get this added as a note to the docs for
ftplib.transfercmd()? IIUC, you must always call ftp.voidresp() after
uploading a file using transfercmd(), and if that's the case, then I
think it'd be helpful to add a note about it in the ftplib docs so
that the next person to come along and try something like this doesn't
run into the same problem.

Thanks,

Kevin

On Thu, 18 Mar 2004 23:17:16 -0800, Kevin Ollivier <kevino at tulane.edu>
Hi all,
I've come across a problem that has me stumped, and I thought I'd send
a message to the gurus to see if this makes sense to anyone else. =)
Basically, I'm trying to upload a series of files via FTP. I'm using
ftplib to do it, and for each file I'm using transfercmd("STOR " +
myfile) to get the socket, then uploading 4096 bytes at a time and
providing status updates via a GUI interface. Finally, I close the
socket, set it to None, then move on to the next file. I'm using
active FTP to upload.
The first file uploads just fine, but on the second file I'm
consistently seeing a weird problem where the response to the PORT
command (sent by self.makeport()) comes *after* the STOR command is
sent. The order in which the commands are sent doesn't seem to differ,
only the order in which the FTP server responds differs. This causes
the transfercmd() call to see an 'error' because the repsonse to the
PORT command is a 200, but it expects a response in the 100s. I've
posted the actual FTP debug calls below.
I can resolve the problem by continually re-logging into the server,
but I'd like to avoid doing that if possible. I've tried setting the
file mode to binary as well as ASCII with the same results.
Any clues on what I may be going wrong? Has anyone seen anything like
this before? I couldn't find anything while googling... TIA for any
help!
Kevin
#uploading first file...
*cmd* u'CWD /newlook/tutorial/'
*put* u'CWD /newlook/tutorial/\r\n'
*get* '250 CWD command successful.\r\n'
*resp* '250 CWD command successful.'
*cmd* 'TYPE I'
*put* 'TYPE I\r\n'
*get* '200 Type set to I.\r\n'
*resp* '200 Type set to I.'
item = /newlook/tutorial/pub/working_with_themes.htm
*cmd* 'PORT 192,168,1,103,13,230'
*put* 'PORT 192,168,1,103,13,230\r\n'
*get* '200 PORT command successful.\r\n'
*resp* '200 PORT command successful.'
*cmd* u'STOR /newlook/tutorial/pub/working_with_themes.htm'
*put* u'STOR /newlook/tutorial/pub/working_with_themes.htm\r\n'
*get* '150 Opening BINARY mode data connection for
/newlook/tutorial/pub/working_with_themes.htm.\r\n'
*resp* '150 Opening BINARY mode data connection for
/newlook/tutorial/pub/working_with_themes.htm.'
*cmd* 'TYPE I'
*put* 'TYPE I\r\n'
*get* '226 Transfer complete.\r\n'
*resp* '226 Transfer complete.'
#uploading second file...
item = /newlook/tutorial/pub/Changing_Page_Properties_1.htm
*cmd* 'PORT 192,168,1,103,13,231'
*put* 'PORT 192,168,1,103,13,231\r\n'
*get* '200 Type set to I.\r\n'
*resp* '200 Type set to I.'
*cmd* u'STOR /newlook/tutorial/pub/Changing_Page_Properties_1.htm'
*put* u'STOR /newlook/tutorial/pub/Changing_Page_Properties_1.htm\r\n'
*get* '200 PORT command successful.\r\n'
*resp* '200 PORT command successful.'
File "F:\oss\eclass\eclass_builder\editor.py", line 1083, in
UploadPage
self.UploadFiles(ftpfiles)
File "F:\oss\eclass\eclass_builder\editor.py", line 921, in
UploadFiles
ftp.UploadFiles()
File "F:\oss\eclass\eclass_builder\editor.py", line 1908, in
UploadFiles
self.mysocket = self.host.transfercmd('STOR ' + dir + myitem)
File "C:\PYTHON23\lib\ftplib.py", line 345, in transfercmd
return self.ntransfercmd(cmd, rest)[0]
File "C:\PYTHON23\lib\ftplib.py", line 336, in ntransfercmd
raise error_reply, resp
ftplib.error_reply: 200 PORT command successful.
Eddie Corns
2004-03-23 15:00:22 UTC
Permalink
Post by Kevin Ollivier
OK, I finally figured out how to fix my problems with the FTP commands
being issued in the wrong order - after I've finished uploading the
file, I have to call ftplib.voidresp().
Is it possible to get this added as a note to the docs for
ftplib.transfercmd()? IIUC, you must always call ftp.voidresp() after
uploading a file using transfercmd(), and if that's the case, then I
think it'd be helpful to add a note about it in the ftplib docs so
that the next person to come along and try something like this doesn't
run into the same problem.
It's more complicated than that. You have to be aware that FTP commands
generate responses, sometimes multiple responses but I think that's so rare
you can ignore it. Most of the ftplib commands hide this, when I replied to
the first post, I could see that the problem was probably that you weren't
eating your responses, unfortunately I didn't read your message carefully
enough to notice you were calling transfercmd directly (tsk tsk) and hence my
explanation was crap (sorry). In general you will often need to know what the
response actually is, however neither of the response gathering methods is
exposed, which is probably worth remedying.

Which brings me to the observation in that in such cases it's often best just
to look at the source. I had a similar problem when trying to turn an FTP
call into a generator but soon noticed all those calls to voidresp.

However it's probably worth trying to get the documentation augmented to
remind users that transfercmd may need to handle responses and to request that
at least getresp be added as a public interface. I think there's a
special mail address for such requests but I'm too lazy^H^H^H^Hbusy to look it
up just now.

Eddie

Kevin Ollivier
2004-03-19 07:17:16 UTC
Permalink
Hi all,

I've come across a problem that has me stumped, and I thought I'd send
a message to the gurus to see if this makes sense to anyone else. =)

Basically, I'm trying to upload a series of files via FTP. I'm using
ftplib to do it, and for each file I'm using transfercmd("STOR " +
myfile) to get the socket, then uploading 4096 bytes at a time and
providing status updates via a GUI interface. Finally, I close the
socket, set it to None, then move on to the next file. I'm using
active FTP to upload.

The first file uploads just fine, but on the second file I'm
consistently seeing a weird problem where the response to the PORT
command (sent by self.makeport()) comes *after* the STOR command is
sent. The order in which the commands are sent doesn't seem to differ,
only the order in which the FTP server responds differs. This causes
the transfercmd() call to see an 'error' because the repsonse to the
PORT command is a 200, but it expects a response in the 100s. I've
posted the actual FTP debug calls below.

I can resolve the problem by continually re-logging into the server,
but I'd like to avoid doing that if possible. I've tried setting the
file mode to binary as well as ASCII with the same results.

Any clues on what I may be going wrong? Has anyone seen anything like
this before? I couldn't find anything while googling... TIA for any
help!

Kevin

#uploading first file...
*cmd* u'CWD /newlook/tutorial/'
*put* u'CWD /newlook/tutorial/\r\n'
*get* '250 CWD command successful.\r\n'
*resp* '250 CWD command successful.'
*cmd* 'TYPE I'
*put* 'TYPE I\r\n'
*get* '200 Type set to I.\r\n'
*resp* '200 Type set to I.'
item = /newlook/tutorial/pub/working_with_themes.htm
*cmd* 'PORT 192,168,1,103,13,230'
*put* 'PORT 192,168,1,103,13,230\r\n'
*get* '200 PORT command successful.\r\n'
*resp* '200 PORT command successful.'
*cmd* u'STOR /newlook/tutorial/pub/working_with_themes.htm'
*put* u'STOR /newlook/tutorial/pub/working_with_themes.htm\r\n'
*get* '150 Opening BINARY mode data connection for
/newlook/tutorial/pub/working_with_themes.htm.\r\n'
*resp* '150 Opening BINARY mode data connection for
/newlook/tutorial/pub/working_with_themes.htm.'
*cmd* 'TYPE I'
*put* 'TYPE I\r\n'
*get* '226 Transfer complete.\r\n'
*resp* '226 Transfer complete.'

#uploading second file...
item = /newlook/tutorial/pub/Changing_Page_Properties_1.htm
*cmd* 'PORT 192,168,1,103,13,231'
*put* 'PORT 192,168,1,103,13,231\r\n'
*get* '200 Type set to I.\r\n'
*resp* '200 Type set to I.'
*cmd* u'STOR /newlook/tutorial/pub/Changing_Page_Properties_1.htm'
*put* u'STOR /newlook/tutorial/pub/Changing_Page_Properties_1.htm\r\n'
*get* '200 PORT command successful.\r\n'
*resp* '200 PORT command successful.'
Traceback (most recent call last):
File "F:\oss\eclass\eclass_builder\editor.py", line 1083, in
UploadPage
self.UploadFiles(ftpfiles)
File "F:\oss\eclass\eclass_builder\editor.py", line 921, in
UploadFiles
ftp.UploadFiles()
File "F:\oss\eclass\eclass_builder\editor.py", line 1908, in
UploadFiles
self.mysocket = self.host.transfercmd('STOR ' + dir + myitem)
File "C:\PYTHON23\lib\ftplib.py", line 345, in transfercmd
return self.ntransfercmd(cmd, rest)[0]
File "C:\PYTHON23\lib\ftplib.py", line 336, in ntransfercmd
raise error_reply, resp
ftplib.error_reply: 200 PORT command successful.
Eddie Corns
2004-03-19 12:22:06 UTC
Permalink
Hi all,
I've come across a problem that has me stumped, and I thought I'd send
a message to the gurus to see if this makes sense to anyone else. =)
Basically, I'm trying to upload a series of files via FTP. I'm using
ftplib to do it, and for each file I'm using transfercmd("STOR " +
myfile) to get the socket, then uploading 4096 bytes at a time and
providing status updates via a GUI interface. Finally, I close the
socket, set it to None, then move on to the next file. I'm using
active FTP to upload.
The first file uploads just fine, but on the second file I'm
consistently seeing a weird problem where the response to the PORT
command (sent by self.makeport()) comes *after* the STOR command is
sent. The order in which the commands are sent doesn't seem to differ,
only the order in which the FTP server responds differs. This causes
the transfercmd() call to see an 'error' because the repsonse to the
PORT command is a 200, but it expects a response in the 100s. I've
posted the actual FTP debug calls below.
I can resolve the problem by continually re-logging into the server,
but I'd like to avoid doing that if possible. I've tried setting the
file mode to binary as well as ASCII with the same results.
Any clues on what I may be going wrong? Has anyone seen anything like
this before? I couldn't find anything while googling... TIA for any
help!
Kevin
#uploading first file...
*cmd* u'CWD /newlook/tutorial/'
*put* u'CWD /newlook/tutorial/\r\n'
*get* '250 CWD command successful.\r\n'
*resp* '250 CWD command successful.'
*cmd* 'TYPE I'
*put* 'TYPE I\r\n'
*get* '200 Type set to I.\r\n'
*resp* '200 Type set to I.'
item = /newlook/tutorial/pub/working_with_themes.htm
*cmd* 'PORT 192,168,1,103,13,230'
*put* 'PORT 192,168,1,103,13,230\r\n'
*get* '200 PORT command successful.\r\n'
*resp* '200 PORT command successful.'
*cmd* u'STOR /newlook/tutorial/pub/working_with_themes.htm'
*put* u'STOR /newlook/tutorial/pub/working_with_themes.htm\r\n'
*get* '150 Opening BINARY mode data connection for
/newlook/tutorial/pub/working_with_themes.htm.\r\n'
*resp* '150 Opening BINARY mode data connection for
/newlook/tutorial/pub/working_with_themes.htm.'
* >*cmd* 'TYPE I'
* >*put* 'TYPE I\r\n'
* >*get* '226 Transfer complete.\r\n'
* >*resp* '226 Transfer complete.'
#uploading second file...
item = /newlook/tutorial/pub/Changing_Page_Properties_1.htm
*cmd* 'PORT 192,168,1,103,13,231'
*put* 'PORT 192,168,1,103,13,231\r\n'
*get* '200 Type set to I.\r\n'
*resp* '200 Type set to I.'
*cmd* u'STOR /newlook/tutorial/pub/Changing_Page_Properties_1.htm'
*put* u'STOR /newlook/tutorial/pub/Changing_Page_Properties_1.htm\r\n'
*get* '200 PORT command successful.\r\n'
*resp* '200 PORT command successful.'
File "F:\oss\eclass\eclass_builder\editor.py", line 1083, in
UploadPage
self.UploadFiles(ftpfiles)
File "F:\oss\eclass\eclass_builder\editor.py", line 921, in
UploadFiles
ftp.UploadFiles()
File "F:\oss\eclass\eclass_builder\editor.py", line 1908, in
UploadFiles
self.mysocket = self.host.transfercmd('STOR ' + dir + myitem)
File "C:\PYTHON23\lib\ftplib.py", line 345, in transfercmd
return self.ntransfercmd(cmd, rest)[0]
File "C:\PYTHON23\lib\ftplib.py", line 336, in ntransfercmd
raise error_reply, resp
ftplib.error_reply: 200 PORT command successful.
I suspect the problem is in the bit marked with *. You are somehow sending
out a new FTP command before the previous was finished. The 226 belonged to
the transfer command but was eaten by the TYPE command, leaving a dangling
response to the TYPE command. Are you perhaps not waiting for the retrbinary
method to finish before sending another? Remember, there is more for
retrbinary to read after it has called the callback for the last time so you
must wait for it to finish.

Eddie
Kevin Ollivier
2004-03-19 18:26:05 UTC
Permalink
On 19 Mar 2004 06:24:13 -0800, stewart at midwinter.ca (Stewart
Post by Stewart Midwinter
The first file uploads just fine, but on the second file I'm
consistently seeing a weird problem where the response to the PORT
command (sent by self.makeport()) comes *after* the STOR command is
sent.
Kevin, when you make a socket connection to the server, are you used
blocking or non-blocking? A blocking connection won't proceed until
it gets a response, while the non-blocking will - and perhaps your
problem lies there. your 2nd command gets a response before the first
one comes back.
I am using whatever method ftplib uses by default, in other words, I
do not explicitly set the socket as blocking or non-blocking.

After reading your reply (and the other I received), I tried
explicitly calling setblocking(1) on both the FTP socket (ftp.sock)
and the socket that is returned when I call transfercmd. However, the
PORT call's response still comes after the STOR command. (As far as I
could tell, setting blocking mode seemed to do nothing.)
Post by Stewart Midwinter
Does indeed your problem only happen at the beginning, or can it
happen anywhere in your list of files?
It does always happen at the beginning, even when uploading to
different servers. But since I cannot get it to upload more than the
first file, I do not know if it would happen at other points in the
upload.

Thanks for your help!

Kevin
Loading...