【问题标题】:What is the right way to manage namespaces in Python 3?在 Python 3 中管理命名空间的正确方法是什么?
【发布时间】:2015-11-29 17:03:57
【问题描述】:

我的大部分编程背景是 C++ 和 Java,但出于职业原因,我开始学习 Python。我注意到的第一件事是 Python 对包和命名空间的新方法,但是在谷歌搜索了一段时间并做了一些实验之后,我想我开始掌握它的窍门了。

然后我读到this,这表明我刚刚学到的一切都是错误的。所以现在我再次感到困惑,我无法弄清楚我应该如何组织我的代码。


这是一个非常具体的问题,我真的不知道如何正确回答任何版本的 Python,尤其是我不知道答案是否从 Python 2 更改为 3。假设我想要一个类一个克隆的 github repo,存储在:

/Users/me/my_teams_code/some_project/package/IWantThisClass.py

但是假设我在这里还有一些其他项目:

/Users/me/my_own_code/some_other_project1/...
/Users/me/my_own_code/some_other_project2/...
/Users/me/my_own_code/some_other_project3/...

每个都使用 IWantThisClass。一种策略似乎是每次都手动将正确的目录添加到 sys.path 中,但这相当麻烦——尤其是当我只是在 Jupyter notebook 中进行试验时。我在谷歌搜索后确定的解决方案是将包目录添加到 bash 中的 PYTHONPATH 变量中;这在“import IWantThisClass”工作得很好的意义上是有效的。但我在上面的 Coghlan 的帖子中读到:

“下一个陷阱存在于所有当前版本的 Python 中,包括 3.3,并且可以总结为以下一般准则:'永远不要将包目录或包内的任何目录直接添加到 Python 路径'。 "

那么解决这个问题的“正确”方法是什么?

【问题讨论】:

  • 你能澄清一下你添加了什么“包目录”吗?该警告的意思是,如果 package 是包含包的顶级 __init__.py 的目录,则应将其 包含 目录添加到路径中。不清楚这是否是您所说的“包目录”。如果不知道示例中的哪些目录具有 __init__.py 并因此是 Python 包,则很难知道应该将哪些目录添加到路径中。
  • 嗯,一条评论是 Python 3 不再需要 init.py 进行导入(我从链接中学到的许多东西之一......),事实上,当我添加/Users/me/my_teams_code/some_package/package 到 PYTHONPATH 导入工作有或没有 init.py。但是为了论证,我们假设目录“包”包含顶级 init.py 文件。
  • 另一条评论:我可能参与了更新我们的代码以符合 Python 3 的过程,所以为了这个问题,让我们将 my_teams_code 的内容视为我可以控制的内容。
  • 如PEP 420 中所述,__init__.py 仅对于命名空间包是可选的。大多数软件包仍然需要__init__.py。

标签: python python-3.x namespaces


【解决方案1】:

基本上,如果package 是您包的顶级目录,您应该将包含 package 的目录添加到sys.path。如果您要导入的不是包而是单个模块(即,只是单个 .py 文件不在包目录中),那么该模块应该在 sys.path/

上的目录中

究竟应该如何添加这些路径是另一个问题。对于我想在路径中添加一次性东西的情况,我发现最简单的方法是在“站点目录”中创建一个.PTH 文件——无论是主站点包目录还是用户- 特定站点包目录。在该.PTH 文件中,您可以列出其他目录,然后将其添加到site.path。因此,您可以拥有自己的 my_stuff.pth 小文件,该文件使用您需要的目录设置 sys.path。这避免了必须向每个脚本添加样板代码来手动修改sys.path。您可以在site module 的文档中了解如何执行此操作。

另一个也许更好的答案是,您应该尽量避免将特定目录添加到 sys.path 以访问特定文件。相反,您应该尝试安装 相关的包,这将让 Python 为您设置路径。如果您正在使用开发中的包,而您不想让主站点包混乱,您可以使用python setup.py develop 或pip install --editable 来“就地”安装包。 (也就是说,包文件将保留在原处,不会移动到全局 Python 站点包中,安装程序将更新相应的 .PTH 文件,以便可以导入新安装的包。)

简而言之,最终您需要远离“这个文件想要这个类来自另一个文件”的方式来查看它。您应该关注的单元是可安装的包或模块。如果您正在编写需要 SomeClass 的代码,您应该安装提供 SomeClass 的包/模块,然后导入它;不要尝试临时操纵sys.path 以针对您想要的单个文件/类而不安装其包。 (如前所述,setup.py develop 和 pip install --editable 允许您执行此操作,同时仍将实际文件保留在您想要的位置。)

【讨论】:

  • 这两种解决方案都有效 - 谢谢!第一个解决方案 - 手动创建 .pth 文件 - 感觉有点像 hack,所以我决定花一点时间学习如何创建可安装的包。从 Python 文档和 Google 搜索中将其拼凑起来非常困难,因为它最终需要大约 10 行代码,但它已经得到了回报,因为该包就像我的虚拟环境中的任何其他包一样工作。
猜你喜欢
  • 2019-09-27
  • 2012-01-03
  • 1970-01-01
  • 1970-01-01
  • 2015-09-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-24
相关资源
最近更新 更多