views:

333

answers:

3

I'm trying to use python to sftp a file, and the code works great in the interactive shell -- even pasting it in all at once.

When I try to import the file (just to compile it), the code hangs with no exceptions or obvious errors.

How do I get the code to compile, or does someone have working code that accomplishes sftp by some other method?

This code hangs right at the ssh.connect() statement:

""" ProblemDemo.py
    Chopped down from the paramiko demo file.

    This code works in the shell but hangs when I try to import it!
"""
from time           import sleep
import os

import paramiko


sOutputFilename     = "redacted.htm"  #-- The payload file

hostname    = "redacted.com"
####-- WARNING!  Embedded passwords!  Remove ASAP.
sUsername   = "redacted"
sPassword   = "redacted"
sTargetDir  = "redacted"

#-- Get host key, if we know one.
hostkeytype = None
hostkey     = None
host_keys   = {}
try:
    host_keys = paramiko.util.load_host_keys(os.path.expanduser('~/.ssh/known_hosts'))
except IOError:
    try:
        # try ~/ssh/ too, because windows can't have a folder named ~/.ssh/
        host_keys = paramiko.util.load_host_keys(os.path.expanduser('~/ssh/known_hosts'))
    except IOError:
        print '*** Unable to open host keys file'
        host_keys = {}

if host_keys.has_key(hostname):
    hostkeytype = host_keys[hostname].keys()[0]
    hostkey     = host_keys[hostname][hostkeytype]
    print 'Using host key of type %s' % hostkeytype


ssh     = paramiko.Transport((hostname, 22))

ssh.connect(username=sUsername, password=sPassword, hostkey=hostkey)

sftp    = paramiko.SFTPClient.from_transport(ssh)

sftp.chdir (sTargetDir)

sftp.put (sOutputFilename, sOutputFilename)

ssh.close()

+1  A: 

This may not be a direct reason why, but rarely do you ever want to have "functionality" executed upon import. Normally you should define a class or function that you then call like this:

import mymodule
mymodule.run()

The "global" code that you run in an import typically should be limited to imports, variable definitions, function and class definitions, and the like...

gahooa
How would such a file be run from the OS?This is not a library, I just imported it to get the pyc file generated.
+3  A: 

That's indeed a bad idea to execute this kind of code at import time, although I am not sure why it hangs - it may be that import mechanism does something strange which interacts badly with paramiko (thread related issues maybe ?). Anyway, the usual solution is to implement the functionality into a function:

def my_expensive_function(args):
    pass

if __name__ == '__main__':
    import sys
    my_expensive_functions(sys.args)

This way, just importing the module will not do anything, but running the script will execute the function with the given arguments at command line.

David Cournapeau
+1 - thread related ;)
JimB
A: 

Weirdness aside, I was just using import to compile the code. Turning the script into a function seems like an unnecessary complication for this kind of application.

Searched for alternate means to compile and found:

import py_compile
py_compile.compile("ProblemDemo.py")

This generated a pyc file that works as intended. So the lesson learned is that import is not a robust way to compile python scripts.

but why would you want to compile your python script in the first place ?
David Cournapeau
It makes it easier to run from windows explorer and windows task scheduler.
I think the correct lesson learned is not to run lengthly or complex code during an import. Perhaps it is "legal" but surely not wise on numerous levels.
gahooa
That is *a* lesson, but the real lesson here is it's corollary: <u>Don't use import to compile ad-hoc scripts</u>. The objective for this question was successful compile. Noobs, like me, are told to use import to get the compiled file -- and it's worked on scores of scripts -- but it's bad advice.
I think you misunderstand what's going on here. Python is not a compiled language. You shouldn't run significant code while a module is being imported; wrap it in a function instead.
alberge