从本地目录导入python包到解释器


86

我正在开发/测试本地目录中的软件包。我想将其导入解释器(v2.5),但是sys.path不包括当前目录。现在我输入sys.path.insert(0,'.')。有没有更好的办法?

也,

from . import mypackage

失败并显示此错误:

ValueError: Attempted relative import in non-package

您在哪里读到了“。” 是Python模块吗?
S.Lott

16
@Lott:这里描述了一个相对的导入路径:docs.python.org/reference/…–
项目发布

1
你可能想看看这个明确的指导chrisyeh96.github.io/2017/08/08/...
凯文·朱

Answers:


44

您只能在从作为包的一部分导入的模块中使用相对导入-您的脚本或交互式解释器不是,因此,当然from . import(这意味着“从与我导入的包相同的导入”)不会不行 import mypackage将被罚款,一旦你确保父目录的mypackagesys.path(你如何设法让你的当前目录sys.path我不知道-你有在site.py一些奇怪的事情,或...)

sys.path实际上,将当前目录放回该目录中没有比将其放入目录中更好的方法了。


用于Ubuntu 8.10的Python 2.5在sys.path中没有用于解释程序的当前目录(空字符串)。我没有进行任何更改,因此以某种方式将其寄出。我刚刚安装了3.0,并且sys.path在sys.path中没有了“”。
项目

@projectshave,好的,Ubuntu无疑有其原因!我没有注意到在8.04(我们目前在工作中使用的是什么),但也许我只是没有给予足够的重视。
亚历克斯·马特利

1
我部分错了。从外壳程序调用的Python在sys.path中具有当前目录。从Emacs调用的Python没有当前目录。奇怪。
项目

1
嗯,那么是Emacs而不是Ubuntu(我不是很了解vim用户;-)。您可以有条件地插入“。” 如果没有,则在sys.path中。
Alex Martelli,2009年

@Alex Martelli:非常感谢!我一直在寻找解决方案,以了解为什么我的附加组件(用于Anki)在作为脚本“本地”运行时需要不同的import语句。相反,当我添加local_launch()方法并从package文件夹外部的脚本中导入/启动整个程序时,它就像一个魅力!
乔恩·库姆斯

17

请参阅sys.path的文档:

http://docs.python.org/library/sys.html#sys.path

报价:

如果脚本目录不可用(例如,如果以交互方式调用解释器或从标准输入中读取脚本),则path [0]为空字符串,它指示Python首先在当前目录中搜索模块。

因此,如果您要从包含模块的目录中启动python解释器,则无需使用sys.path。

另外,要导入您的软件包,只需执行以下操作:

import mypackage

由于包含该软件包的目录已经在sys.path中,因此应该可以正常工作。


1
如果工作环境中的其他位置存在类似的文件名,它将失败。
JAR.JAR.beans

@ JAR.JAR.beans当前工作目录应该是其中的第一件事,sys.path因此应该在工作环境中其他任何位置的文件之前找到文件。
SpoonMeiser '16

3
好点子。也就是说,如果我们从本地目录运行文件。如果是其他文件夹,并且需要更改sys.path,则表示sys.path.insert(0, new_path)而不是sys.path.append(new_path)
JAR.JAR.beans

14

如果要运行未修改的python脚本,以便从特定的本地目录导入库,则可以设置PYTHONPATH环境变量-例如在bash中:

export PYTHONPATH=/home/user/my_libs
python myscript.py

如果只希望它从当前工作目录导入,请使用.符号:

export PYTHONPATH=.
python myscript.py

导出PYTHONPATH包括在python外部进行编程(例如,在bash中)。另外,在docs.python.org/3/using/cmdline.html中明确指出“默认搜索路径取决于安装”。
ilias iliadis

13

把事情简单化:

 try:
     from . import mymodule     # "myapp" case
 except:
     import mymodule            # "__main__" case

7
我喜欢这种解决方案,这是最简单的。唯一剩下的问题是,为什么“只有一个办法做到这一点”实施进口时的规则已被认为是可选的...说真的有大约15种方式申报和组织包,所有这些都有缺点
莱奥Germond

5

一种简单的工作方式是使用python的-m标志从父目录运行脚本,例如python -m packagename.scriptname。显然,在这种情况下,您需要一个__init__.py文件将目录转换为包。


5

在软件包中,如果有setup.py,则最好安装它

pip install -e .

3

使用sys.path应该已经包括当前目录。

尝试:

import .

要么:

from . import sth

但是,这可能不是一个好习惯,所以为什么不直接使用:

import mypackage

5
<import mypackage>的问题是它将从全局python env加载程序包,可能会从本地文件夹加载程序包/文件,但也可能会加载正在工作的env中的其他随机mypackge。
JAR.JAR.beans

2

开派对有点晚,但这对我有用:

>>> import sys
>>> sys.path.insert(0, '')

显然,如果有一个空字符串,Python知道它应该在当前目录中查找。我在中没有空字符串sys.path,这导致了此错误。


0

我曾经pathlib将模块目录添加到系统路径中,因为我想避免将模块作为软件包安装,并且@maninthecomputer响应对我不起作用

import sys
from pathlib import Path

cwd = str(Path(__file__).parent)
sys.path.insert(0, cwd)
from my_module import my_function
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.