python ftplib hangs on upload (STOR) --- and not network latency

1.5k Views Asked by At

I have a very simple utility script using ftplib on python 2.7 to upload web files to my remote host. However, storlines hangs and just sits there for a couple of minutes. Doesn't have the decency to throw any kind of exception.

  • I've verified that the connection works from the REPL. storlines hangs both from the REPL and from the commandline script.

  • my test file is 22 bytes (not KB, bytes), so it seems very unlikely that things are just timing out. Also, at the REPL, after I kill the hung upload via cntrl-c, I can get output from ftp.dir(), so I know I'm not losing the connection at some point.

  • the aforementioned output from ftp.dir() is much larger than my test file, and arrives within a few seconds, so I know the problem isn't network latency.

  • based on this prior SO I've tried adding ftp.set_pasv(False) before the upload function definition, but that does nada.

Does anyone else have any ideas about what could be going wrong here? Here's the code:

import sys
from ftplib import FTP
ftp = FTP([MYSERVER], [MYUSER], [MYPASSWORD])
full = sys.argv[1]
path = 'public_html/' + full[:full.rfind('/') + 1]
filename = full[full.rfind('/') + 1:]
ftp.cwd(path)

def upload(method, mode, filename):
    with open(filename, mode) as fileobject:
        method('STOR' +filename, fileobject)

if filename.endswith(('.htm','.html','.py','.cgi','.js','.css','.txt','.md', '.svg')):
    upload(ftp.storlines, 'r', filename)
else:
    upload(ftp.storbinary, 'rb', filename)
ftp.quit()
print 'Done!'

and, seriously, this is the full file I'm trying to upload, with the filename test.md:

this is a test. 
#test
2

There are 2 best solutions below

0
Paul Gowder On

So this is ugly, but I eventually figured out a hack-tastic solution, which just lets the nice existing ftp application that was written by someone who actually knows networking do the work:

import sys
import os
full = sys.argv[1]
path = 'public_html/' + full[:full.rfind('/') + 1]
filename = full[full.rfind('/') + 1:]

def picktype(filename):
    if filename.endswith(('.htm','.html','.py','.cgi','.js','.css','.txt','.md', '.svg')):
        return 'ascii'
    return 'binary'

ftpstring = """
open [SERVER]
user [USER] [PASSWORD]
cd {0}
{1}
put {2}
bye
""".format(path, picktype(filename), filename)

print ftpstring

with open("tempfile.txt", 'w') as tempfile:
    tempfile.write(ftpstring)

os.system('ftp -n < tempfile.txt')

print 'Done!'

I know these days you're supposed to use the subprocess module for this kind of junk, but I can't for the life of me figure out how to make a redirection work.

0
funway On

I had encountered the same problem likes your's. my python ftp script hangs without any output when i run it in ms cmd console. I even rewrite my script with multithread, multiprocess but it doesn't work. But i found my script works normally in linux, or in pycharm ide on windows.

so i think it maybe some problem with ms cmd environment. and then i found those issue python program stops in command line, command freezing.

I try to disable "QuickEdit Mode" option of cmd. it works!