【问题标题】:Cannot import twisted's internet module无法导入twisted的internet模块
【发布时间】:2012-02-06 11:08:22
【问题描述】:

执行 python 协议/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

【问题讨论】:

  • “python -c 'import twisted; print twisted.__file__'”的输出是什么?

标签: python namespaces package twisted


【解决方案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. 尽量简化这一点,并上传导致问题的一组文件的complete, runnable example。由于我不知道这些 .py 文件中的内容,所以我不得不猜测原因。

最终,我认为您看到的问题是由名为 protocols 的顶级模块的组合引起的,它与 Twisted 中的几个模块冲突,以及 import * 的使用可能会拉入另一个像 basicsmtppop3 这样的名称进入该命名空间并与某些东西发生冲突,然后命名空间包的魔力与这一切结合起来产生爆炸。如果没有看到触发问题的实际代码,我不能比这更具体:)。

不过,每当遇到这样的问题时,最好退后一步,确保工作目录、脚本目录和 PYTHONPATH 都分开了,这样您就可以准确地知道代码是如何被导入的。具体来说,我建议这样做:

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

希望对你有更好的效果。

【讨论】:

  • 我已经更新了这个问题,因为评论不支持格式化(看起来..)
  • 感谢您的指导!事实上, print twisted.__file__ 指出我这是冲突的导入。由 absolute_import 解决
猜你喜欢
  • 2012-11-06
  • 1970-01-01
  • 1970-01-01
  • 2017-11-11
  • 2021-07-27
  • 2019-06-13
  • 2020-12-15
  • 2020-08-28
相关资源
最近更新 更多