从Python中的相对路径导入

Dre*_*rew 86 python import relative-path shared-libraries python-3.x

我有一个用于我的客户端代码的文件夹,一个用于我的服务器代码的文件夹,以及一个用于它们之间共享的代码的文件夹

Proj/
    Client/
        Client.py
    Server/
        Server.py
    Common/
        __init__.py
        Common.py
Run Code Online (Sandbox Code Playgroud)

如何从Server.py和Client.py导入Common.py?

Dav*_*ave 122

编辑2014年11月(3年后):

Python 2.6和3.x支持正确的相对导入,你可以避免做任何hacky.使用此方法,您知道您正在获取相对导入而不是绝对导入.'..'表示,转到我上面的目录:

from ..Common import Common
Run Code Online (Sandbox Code Playgroud)

作为一个警告,只有从包外部运行python作为模块时,这才有效.例如:

python -m Proj
Run Code Online (Sandbox Code Playgroud)

原来的hacky方式

在某些情况下,此方法仍然常用,您实际上并未"安装"您的软件包.例如,它受Django用户的欢迎.

您可以将Common /添加到您的sys.path(python查看导入内容的路径列表):

import sys, os
sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'Common'))
import Common
Run Code Online (Sandbox Code Playgroud)

os.path.dirname(__file__) 只是给你当前python文件所在的目录,然后我们导航到'Common /'目录并导入'Common'模块.

  • 感谢您回答实际问题而不是讲述正确的技巧.进行相对进口有很多充分的理由. (26认同)
  • @WattsInABox 您将如何转到不同目录中的文件,相当于“../../mydir2/myfile”? (6认同)
  • 再上一层,每层使用一个额外的点.@jxramos ex:`from ... myfile`转到`../../ myfile` (5认同)
  • 不要手动修改python模块路径,可能只是为了快速破解.使用distutils,setuptools等学习Python包管理通常是解决这类问题的必备技能. (2认同)

Mic*_*jer 10

不做相对导入.

来自PEP8:

不鼓励进行包装内进口的相对进口.

将所有代码放入一个超级包(即"myapp")中,并使用子包作为客户端,服务器和公共代码.

更新: " Python 2.6和3.x支持正确的相对导入(...) ".有关详细信息,请参阅Dave的答案.

  • 令我感到惊讶的是,"不要这样做"是"我怎么......"问题的公认答案(好吧,除了Rails <g>.)**偶尔会有**这样做的理由.我使用类似于戴夫建议的解决方案. (77认同)
  • 此答案不适用于当前版本的Python.在PEP 8中不再能够找到引用的部分.现在它的内容如下:_"显式相对导入是绝对导入的可接受替代方案,尤其是在处理复杂的包布局时,使用绝对导入会不必要地冗长"_ (10认同)
  • 有人应该在Numpy告诉大家!他们使用相对进口的吨! (2认同)

小智 7

做相对导入是绝对可以的!这就是我的小事:

#first change the cwd to the script path
scriptPath = os.path.realpath(os.path.dirname(sys.argv[0]))
os.chdir(scriptPath)

#append the relative location you want to import from
sys.path.append("../common")

#import your module stored in '../common'
import common.py
Run Code Online (Sandbox Code Playgroud)

  • 但你最好知道 sys.argv[0] 实际上指向哪里 - 它(很可能)不是你启动 python 时所在的目录。 (2认同)

小智 7

有趣的是,我遇到了同样的问题,我按照以下方式完成了这项工作:

结合linux命令ln,我们可以让事情变得更加简单:

1. cd Proj/Client
2. ln -s ../Common ./

3. cd Proj/Server
4. ln -s ../Common ./
Run Code Online (Sandbox Code Playgroud)

而且,现在如果你想some_stuff从file:Proj/Common/Common.py导入你的文件:Proj/Client/Client.py,就像这样:

# in Proj/Client/Client.py
from Common.Common import some_stuff
Run Code Online (Sandbox Code Playgroud)

并且,同样适用于Proj/Server,也适用于setup.py流程, 这里讨论的同一个问题,希望它有所帮助!


Jon*_*erg 6

默认导入方法已经是“相对”的,来自 PYTHONPATH。PYTHONPATH 默认情况下与原始源文件的文件夹一起指向某些系统库。如果使用 -m 运行模块,当前目录将添加到 PYTHONPATH 中。因此,如果程序的入口点位于 Proj 内部,则使用import Common.Common应该在 Server.py 和 Client.py 内部都有效。

不要进行相对导入。它不会按照你想要的方式工作。