我试图找出这是我的设计错误还是redis-py库错误。从本质上讲,我对Python中名称空间的理解是,应该对程序包进行设计,使所有组件都位于程序包名称空间下。这意味着,如果我在packageA中有一个队列,而在packageB中有一个队列,则应该没有冲突,因为它们是命名空间(packageA.queue和packageB.queue)。但是,我在构建的软件包中遇到错误。
这是我正在构建的软件包的目录结构:
○ → tree
.
├── __init__.py
├── net
│ ├── __init__.py
│ ├── rconn.py
└── test.py
__init__.py
文件均为空。这是我的test.py文件的代码:
○ → cat test.py
from net import rconn
这是我的net / rconn.py文件中的代码:
○ → cat net/rconn.py
import redis
运行test.py,一切正常,没有错误。但是,如果我在此处添加队列目录并在其中创建一个空的init.py,则这是新树:
○ → tree
.
├── __init__.py
├── net
│ ├── __init__.py
│ ├── rconn.py
├── queue
│ ├── __init__.py
└── test.py
运行test.py会导致以下错误:
Traceback (most recent call last):
File "test.py", line 1, in <module>
from net.rconn import ass
File "/Users/yosoyunmaricon/python_test/net/rconn.py", line 1, in <module>
import redis
File "/usr/local/lib/python3.7/site-packages/redis/__init__.py", line 1, in <module>
from redis.client import Redis, StrictRedis
File "/usr/local/lib/python3.7/site-packages/redis/client.py", line 10, in <module>
from redis._compat import (b, basestring, bytes, imap, iteritems, iterkeys,
File "/usr/local/lib/python3.7/site-packages/redis/_compat.py", line 139, in <module>
from queue import Queue
ImportError: cannot import name 'Queue' from 'queue' (/Users/yosoyunmaricon/python_test/queue/__init__.py)
所以,我知道发生了什么事。 Redis代码显示from queue import Queue
,当我创建一个空队列目录(即无队列)时,它会破坏软件包。我的问题是:那是好的设计吗? Redis软件包是否应该更明确,并像from redis.queue import Queue
那样说些什么,或者这仅仅是我自己设计中的错误?
答案 0 :(得分:1)
不是Redis软件包应该在这里进行调整,因为它无法知道或无法处理用户将Redis软件包集成到自己的应用程序中的不同方式,例如您具有类似名称的queue
软件包。此外,没有redis.queue
,因为该queue
不是redis
的一部分,而是built-in Python queue
package。您可以转到 /usr/local/lib/python3.7/site-packages/redis/_compat.py 并打印出queue.__file__
,这将为您提供Python { {1}}。它期望导入内置的queue
程序包。
不幸的是,当Python构建module search paths用于解析导入时,它会按以下顺序构建它:
- 包含输入脚本的目录(如果未指定文件,则为当前目录)。
queue
(目录名称列表,语法与shell变量PYTHONPATH
相同)。- 与安装有关的默认设置。
...这会将您自己的PATH
放在列表的开头,这就是要导入的内容。因此,是的,因为您遮盖了内置queue
而导致ImportError,在您自己的设计中更多是一个错误。
您可以在此处使用queue
或sys.path
来完成一些技巧,但是当您只需要将PYTHONPATH
重命名为其他名称时,为什么还要打扰。或者,我通常要做的是将自己的软件包分组到一个父文件夹中,该文件夹以项目的首字母缩写(“ queue
”或某些应用程序标识或“ mylibs ”之类的名称命名:
abcdlibs
这样,您可以清楚地知道.
├── __init__.py
├── mylibs
│ └── queue
│ ├── __init__.py
├── mynet
│ ├── __init__.py
│ └── rconn.py
└── test.py
与mylibs.queue
不同。