为什么这个python代码挂起导入/编译但在shell中工作?

Why does this python code hang on import/compile but work in the shell?

我尝试使用python来sftp一个文件,代码在交互式shell中工作得很好——甚至可以同时粘贴它。

当我试图导入文件(只是为了编译它)时,代码挂起,没有异常或明显的错误。

如何让代码进行编译,或者某人是否有通过其他方法完成sftp的工作代码?

此代码正好挂在ssh.connect()语句上:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
""" 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()


在导入时执行这种代码确实是一个坏主意,尽管我不确定它为什么挂起——可能是导入机制做了一些奇怪的事情,它与Paramiko(线程相关的问题,可能是吗?)。无论如何,通常的解决方案是将功能实现为一个函数:

1
2
3
4
5
6
def my_expensive_function(args):
    pass

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

这样,只导入模块不会做任何事情,但运行脚本将在命令行使用给定参数执行函数。


这可能不是一个直接的原因,但很少有人希望在导入时执行"功能"。通常,您应该定义一个类或函数,然后这样调用它:

1
2
import mymodule
mymodule.run()

在导入中运行的"全局"代码通常应限于导入、变量定义、函数和类定义等…


奇怪的是,我只是用import来编译代码。对于这种应用程序来说,将脚本转换为函数似乎是不必要的复杂操作。

寻找替代手段编译并发现:

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

这生成了一个按预期工作的pyc文件。因此,我们学到的经验是,导入并不是编译Python脚本的可靠方法。