将Python搜索路径扩展到其他源

时间:2010-06-29 19:37:43

标签: python search import path

我刚刚加入了一个拥有相当大的现有代码库的项目。我们在linux中开发并且不使用和IDE。我们通过命令行运行。我正在试图弄清楚如何在运行项目模块时让python搜索正确的路径。例如,当我运行类似的东西时:

python someprojectfile.py

我得到了

ImportError: no module named core.'somemodule'

我得到了所有导入的内容,我认为这是路径的问题。

TLDR:

如何让Python在导入语句中搜索~/codez/project/以及* .py文件的所有文件和文件夹。

7 个答案:

答案 0 :(得分:140)

有几种方法可以做到这一点:

  • 将环境变量PYTHONPATH设置为以冒号分隔的目录列表,以搜索导入的模块。
  • 在您的程序中,使用sys.path.append('/path/to/search')添加您希望Python搜索导入模块的目录名称。 sys.path只是Python每次被要求导入模块时搜索的目录列表,您可以根据需要对其进行更改(尽管我不建议删除任何标准目录!)。在Python启动时,您放入环境变量PYTHONPATH的任何目录都将插入sys.path
  • 使用site.addsitedir将目录添加到sys.path。这个和简单附加的区别在于,当您使用addsitedir时,它还会查找该目录中的.pth个文件,并使用它们根据内容可能向sys.path添加其他目录的文件。有关更多详细信息,请参阅文档。

您要使用哪一种取决于您的情况。请记住,当您将项目分发给其他用户时,他们通常会以这样的方式安装它,即Python的导入器会自动检测Python代码文件(即包通常安装在site-packages目录中),所以如果你在您的代码中弄乱sys.path,这可能是不必要的,甚至可能在该代码在另一台计算机上运行时产生负面影响。对于开发,我猜想设置PYTHONPATH通常是最好的方法。

但是,当您使用的东西只能在您自己的计算机上运行时(或者您有非标准设置时,例如有时在Web应用程序框架中),执行类似

的操作并不罕见
from os.path import dirname
sys.path.append(dirname(__file__))

答案 1 :(得分:11)

您还应该在这里阅读有关python包的信息:http://docs.python.org/tutorial/modules.html

从你的例子中,我猜你确实在~/codez/project有一个包。 python目录中的文件__init__.py将目录映射到命名空间。如果您的子目录都有__init__.py文件,那么您只需要将基目录添加到PYTHONPATH。例如:

  

PYTHONPATH = $ PYTHONPATH:$ HOME / adaifotis /项目

除了测试你的PYTHONPATH环境变量之外,正如David解释的那样,你可以在python中测试它,如下所示:

$ python
>>> import project                      # should work if PYTHONPATH set
>>> import sys
>>> for line in sys.path: print line    # print current python path

...

答案 2 :(得分:4)

我知道这个帖子有点老了,但我花了一些时间才弄明白这一点,所以我想分享。

在我的项目中,我将主脚本放在父目录中,为了区分模块,我将所有支持模块放在一个名为“modules”的子文件夹中。在我的主脚本中,我导入这些模块(对于一个名为report.py的模块):

from modules.report import report, reportError

如果我调用我的主脚本,这是有效的。但是,我想通过在每个模块中包含main()来测试每个模块,并直接调用每个模块,如下所示:

python modules/report.py

现在Python抱怨它无法找到“一个名为模块的模块”。这里的关键是,默认情况下,Python在其搜索路径中包含脚本的文件夹,但不包括CWD。所以这个错误说的真的是“我找不到模块子文件夹”。这是因为report.py模块所在的目录中没有“modules”子目录。

我发现最好的解决方案是将CWD附加到Python搜索路径中,将其包含在顶部:

import sys

sys.path.append(".")

现在Python搜索CWD(当前目录),找到“modules”子文件夹,一切都很顺利。

答案 3 :(得分:2)

我读这个问题寻找答案,并不喜欢其中任何一个。

所以我写了一个快速而肮脏的解决方案。只需将它放在sys.path上的某个位置,它就会在folder(从当前工作目录)或abspath下添加任何目录:

#using.py

import sys, os.path

def all_from(folder='', abspath=None):
    """add all dirs under `folder` to sys.path if any .py files are found.
    Use an abspath if you'd rather do it that way.

    Uses the current working directory as the location of using.py. 
    Keep in mind that os.walk goes *all the way* down the directory tree.
    With that, try not to use this on something too close to '/'

    """
    add = set(sys.path)
    if abspath is None:
        cwd = os.path.abspath(os.path.curdir)
        abspath = os.path.join(cwd, folder)
    for root, dirs, files in os.walk(abspath):
        for f in files:
            if f[-3:] in '.py':
                add.add(root)
                break
    for i in add: sys.path.append(i)

>>> import using, sys, pprint
>>> using.all_from('py') #if in ~, /home/user/py/
>>> pprint.pprint(sys.path)
[
#that was easy
]

我喜欢它,因为我可以拥有一个随机工具的文件夹,而不是让它们成为包或任何东西的一部分,并且仍然可以通过几行代码访问它们中的一些(或全部)。

答案 4 :(得分:2)

我找到的最简单的方法是创建一个文件" any_name.pth"并将其放在您的文件夹" \ Lib \ site-packages"中。你应该在任何安装python的地方找到该文件夹​​。

在该文件中,放置要保留要导入的模块的目录列表。例如,在该文件中创建一行,如下所示:

C:\用户\示例... \示例

你可以通过在python中运行它来告诉它有效:

import sys
for line in sys: print line

您将看到打印出的目录,以及您可以导入的目录。现在你可以导入一个" mymodule.py"位于该目录中的文件很容易:

import mymodule

这不会导入子文件夹。为此你可以设想创建一个python脚本来创建一个包含你定义的文件夹的所有子文件夹的.pth文件。让它在启动时运行。

答案 5 :(得分:0)

旧问题的新选项。
在Debian上安装fail2ban软件包,似乎已硬编码在/usr/lib/python3/dist-packages/fail2ban上安装了不在python3 sys.path上的路径。


> python3
Python 3.7.3 (v3.7.3:ef4ec6ed12, Jun 25 2019, 18:51:50)
[GCC 6.3.0 20170516] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.path
['', '/usr/lib/python37.zip', '/usr/lib/python3.7', '/usr/lib/python3.7/lib-dynload', '/usr/lib/python3.7/site-packages']
>>>

因此,我(bash)将库与较新的版本联系在一起,而不仅仅是复制。
对原始应用程序的未来更新也将自动应用于链接的版本。

 if [ -d /usr/lib/python3/dist-packages/fail2ban ]
   then
      for d in /usr/lib/python3.*
      do
         [ -d ${d}/fail2ban ] || \
            ln -vs /usr/lib/python3/dist-packages/fail2ban ${d}/
      done
   fi

答案 6 :(得分:0)

第一个任务是找出当前环境从哪里获取其标准库。这就是我存储 OOP 模块的地方。

computed: {
    userlist: function(){
        // here, this is the component instance
        return this.users.filter((user) => { // --> replaced function with an  arrow function
            // here, this is still a reference to the component instance
            return user.name.toLowerCase().match(this.search.toLowerCase())
        });
    }
}

您将获得有关您的环境的目录。对于另一台计算机,最好为 OOP 模块创建一个单独的目录。

Import numpy

numpy.__file__