无法导入twisted的internet模块

1 投票
1 回答
1041 浏览
提问于 2025-04-17 09:53

我在执行 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

这里有几个可能的问题。

  1. Wass真的是一个包吗?还是说它只是sys.path上的一个条目?如果它真的是一个包,你应该把/tmp加到你的PYTHONPATH里;如果它只是一个路径条目,你应该把/tmp/Wass加到PYTHONPATH里,并删除/tmp/Wass/__init__.py*
  2. 不要直接在层级结构中的模块上运行python。这样会让事情变得复杂。
  3. 如果Wass会继续作为一个包存在(也就是说,它里面有一个__init__.py文件),你应该调整你的导入方式,改成from Wass.protocols.smpp.proto import ...
  4. 不要使用import *。这样会让人困惑;看你代码的人根本不知道哪些名字是从哪个模块来的。
  5. 尽量简化问题,并上传一个完整且可运行的示例,展示导致问题的一组文件。因为我不知道那些.py文件里有什么,只能猜测问题的原因。

我觉得你遇到的问题可能是因为有一个顶层模块叫protocols,它和Twisted里面的几个模块发生了冲突,再加上使用import *,这可能把其他名字像basicsmtppop3引入了这个命名空间,导致了冲突,最后命名空间包的魔力让这一切结合在一起,产生了问题。我不能更具体地说,因为我没有看到实际触发问题的代码 :)。

每当遇到这样的情况,最好退一步,确保工作目录、脚本目录和PYTHONPATH都是分开的,这样你就能清楚地知道你的代码是如何被导入的。具体来说,我建议你可以这样做:

$ cd /tmp
$ mkdir runstuff
$ cd runstuff
$ PYTHONPATH=/tmp/Wass trial protocols

希望这样能对你更有帮助。

撰写回答