本地目录影子第三方软件包

时间:2019-12-22 10:38:30

标签: python-3.x oop namespaces

我试图找出这是我的设计错误还是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那样说些什么,或者这仅仅是我自己设计中的错误?

1 个答案:

答案 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,在您自己的设计中更多是一个错误。

您可以在此处使用queuesys.path来完成一些技巧,但是当您只需要将PYTHONPATH重命名为其他名称时,为什么还要打扰。或者,我通常要做的是将自己的软件包分组到一个父文件夹中,该文件夹以项目的首字母缩写(“ queue”或某些应用程序标识或“ mylibs ”之类的名称命名:

abcdlibs

这样,您可以清楚地知道. ├── __init__.py ├── mylibs │ └── queue │ ├── __init__.py ├── mynet │ ├── __init__.py │ └── rconn.py └── test.py mylibs.queue不同。