无法导入twisted的internet模块
我在执行 python protocols/smpp/test/test_post_upgrade.py 时遇到了以下错误:
Traceback (most recent call last):
File "protocols/smpp/test/test_post_upgrade.py", line 1, in <module>
from protocols.smpp.proto import *
File "/tmp/Wass/protocols/smpp/proto.py", line 1, in <module>
from twisted.internet import defer, reactor
ImportError: No module named internet
这是我的文件结构:
/tmp/Wass$ tree
.
├── __init__.py
└── protocols
├── __init__.py
├── __init__.pyc
└── smpp
├── __init__.py
├── __init__.pyc
├── proto.py
├── proto.pyc
└── test
├── __init__.py
└── test_post_upgrade.py
3 directories, 10 files
这是主要文件的内容:
/tmp/Wass$ cat protocols/smpp/proto.py
from twisted.internet import defer, reactor
/tmp/Wass$ cat protocols/smpp/test/test_post_upgrade.py
from protocols.smpp.proto import *
/tmp/Wass$ cat protocols/smpp/__init__.py
__import__('pkg_resources').declare_namespace(__name__)
为了说明,我可以通过以下几种方式解决这个问题:
- 清空
protocols/smpp/__init__.py
文件,但这个文件对整个项目是有用的,所以我不能随便清空它,否则我的项目就无法运行了。 - 把
protocols/smpp
改成其他名字,比如改成protocols/toto
就可以正常工作(同时需要把protocols/smpp/test/test_post_upgrade.py
中的内容改为from protocols.toto.proto import *
)。
第二个解决方案让我很困惑,因为我系统中并没有任何 smpp/proto.py
文件会导致冲突……
这是问题的一个更简单的描述:
Wass/
Wass/__init__.py
Wass/protocols/
Wass/protocols/smpp/
Wass/protocols/smpp/__init__.py
Wass/protocols/smpp/test/
Wass/protocols/smpp/test/__init__.py
Wass/protocols/__init__.py
Wass/protocols/smpp/test/test_post_upgrade.py:
> from Wass.protocols.smpp.proto import SMPPClientProtocol
Wass/protocols/smpp/proto.py
> from twisted.internet import defer, reactor
>
> class SMPPClientProtocol:
> pass
执行结果:
$ echo $PYTHONPATH
:/opt/smpp.twisted/:/opt/smpp.pdu/:/tmp/Wass/
python /tmp/Wass/protocols/smpp/test/test_post_upgrade.py
> Returns the same problem above
1 个回答
1
这里有几个可能的问题。
Wass
真的是一个包吗?还是说它只是sys.path
上的一个条目?如果它真的是一个包,你应该把/tmp
加到你的PYTHONPATH
里;如果它只是一个路径条目,你应该把/tmp/Wass
加到PYTHONPATH
里,并删除/tmp/Wass/__init__.py*
。- 不要直接在层级结构中的模块上运行
python
。这样会让事情变得复杂。 - 如果
Wass
会继续作为一个包存在(也就是说,它里面有一个__init__.py
文件),你应该调整你的导入方式,改成from Wass.protocols.smpp.proto import ...
。 - 不要使用
import *
。这样会让人困惑;看你代码的人根本不知道哪些名字是从哪个模块来的。 - 尽量简化问题,并上传一个完整且可运行的示例,展示导致问题的一组文件。因为我不知道那些.py文件里有什么,只能猜测问题的原因。
我觉得你遇到的问题可能是因为有一个顶层模块叫protocols
,它和Twisted里面的几个模块发生了冲突,再加上使用import *
,这可能把其他名字像basic
、smtp
或pop3
引入了这个命名空间,导致了冲突,最后命名空间包的魔力让这一切结合在一起,产生了问题。我不能更具体地说,因为我没有看到实际触发问题的代码 :)。
每当遇到这样的情况,最好退一步,确保工作目录、脚本目录和PYTHONPATH都是分开的,这样你就能清楚地知道你的代码是如何被导入的。具体来说,我建议你可以这样做:
$ cd /tmp
$ mkdir runstuff
$ cd runstuff
$ PYTHONPATH=/tmp/Wass trial protocols
希望这样能对你更有帮助。