我是否需要将项目目录添加到每个脚本中的系统路径以从另一个目录导入函数?

时间:2018-02-13 04:28:48

标签: python

我试图让数据科学项目井井有条,所以我在我的src目录中创建了一个名为utils的目录,其中包含一个名为{{1}的文件},包含一些将在许多脚本中使用的辅助函数。如何将helpers.pyfunc_name导入到完全不同的目录中的文件(例如src/utils/helpers.py

>的最佳做法是什么?

我看到answers这个问题,我已经实施了一个有效的解决方案,但这感觉很难看:

src/processing/clean_data.py

我这样做了吗?我是否需要将此添加到要导入 sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))))) 的每个脚本,例如func_name

我当前的项目文件夹结构:

train_model.py

示例文件:

myproject
    /notebooks
        notebook.ipynb
    /src
        /processing
            clean_data.py
        /utils
            helpers.py
        /models
            train_model.py
        __init__.py

7 个答案:

答案 0 :(得分:6)

正确的方法是使用__init__.pysetup.pysetuptools Python包:

myPackage/
    myPackage/
        __init__.py
    setup.py

link包含所有步骤。

答案 1 :(得分:4)

首先,让我来描述 Python模块和&之间的区别。一个 Python包,以便我们俩都在同一页面上。 ✌

模块是单个.py文件(或多个文件),它们在一个导入下导入并使用。 ✔

import aModuleName # Here 'aModuleName' is just a regular .py file.

然而,包是给出包层次结构的目录中的模块集合。包中包含不同的 __init__.py 文件。 ✔

from aPackageName import aModuleName # Here 'aPackageName` is a folder with a `__init__.py` file # and 'aModuleName', which is just a regular .py file.

因此,当我们有一个名为 proj-dir 的项目目录时,⤵

proj-dir --|--__init__.py --package1 --|--__init__.py --|--module1.py --package2 --|--__init__.py --|--module2.py

  

请注意,我还在 proj-dir 本身添加了一个空的 __init__.py ,这也使它成为一个包。

现在,如果要将 package2 module2 中的任何python对象导入 package1 module1 ,然后 module1.py 文件中的导入语句将

from package2.module2 import object2 # if you were to import the entire module2 then, from package2 import module2

我希望这个简单的解释能够澄清你对Python导入的怀疑。机制并解决了这个问题。如果没有,那么在这里做评论。

答案 2 :(得分:1)

首先让我澄清一下,如果要使用其中的一部分,导入整个模块,则不是一个好主意。而不是你可以使用from导入库/包下的特定功能。通过这样做,您可以使您的程序在内存和性能方面更高效。

要了解更多信息,请参阅:

  1. 'import module' or 'from module import'
  2. difference between import and from
  3. Net让我们看看解决方案。

    在开始使用解决方案之前,让我向您澄清__init__.py文件的使用。它告诉python解释器,存在的 *。py 文件是可导入的,这意味着它们是模块,而是/可能是包的一部分。

    因此,如果您没有N个子目录,则必须将__init__.py文件放在所有这些子目录中,以便也可以导入它们。在__init__.py文件内,您还可以添加一些其他信息,例如应包含哪些路径,默认函数,变量,范围等等。要了解这些只是谷歌关于__init__.py文件或采取一些python库并通过相同的__init__.py文件来了解它。 (这就是解决方案)

    更多信息:

    1. modules
    2. Be pythonic
    3. 正如@Sushant Chaudhary所述,您的项目结构应该像

      proj-dir
       --|--__init__.py
         --package1
           --|--__init__.py
           --|--module1.py
         --package2
           --|--__init__.py
           --|--module2.py
      
        

      现在,如果我将__init__.py文件放在我上面的目录下,Will   它可以导入并且工作正常吗?

           

      是和否

      是:

      如果要导入该项目/包目录中的模块。 例如在你的情况下  您将pakage2.module2中的package1.module1导入为from package1 import module1

      您必须在子模块中导入基础目录 为什么? 如果您运行模块,项目将正常运行来自同一个地方。 即:在package2中作为python module2.py 但是 将抛出ModuleNotFoundError如果从其他目录运行模块。 ,即除了package2 之外的任何其他路径,例如在proj-dir下为python package2/module2.py。这就是你的情况。您正在从project-dir运行该模块。

      那么如何解决这个问题?

      1-您必须将module2.ad中的系统路径的基线路径附加为

      from sys import path
      dir_path = "/absolute/path/to/proj-dir"
      sys.path.insert(0, dir_path)
      

      这样module2就能找到package1(和其中的module1)。

      2-你必须在proj-dir下的__init__.py文件中添加所有子模块路径。

      例如:

      #__init__.py under lxml
      # this is a package
      
      def get_include():
          """
          Returns a list of header include paths (for lxml itself, libxml2
          and libxslt) needed to compile C code against lxml if it was built
          with statically linked libraries.
          """
          import os
          lxml_path = __path__[0]
          include_path = os.path.join(lxml_path, 'includes')
          includes = [include_path, lxml_path]
      
          for name in os.listdir(include_path):
              path = os.path.join(include_path, name)
              if os.path.isdir(path):
                  includes.append(path)
      
          return includes
      

      这是 lxml __init__.py文件(用于解析html,xml数据的python库)。您可以在具有子模块的任何python库下引用任何__init__.py文件。 ex(os,sys)。我在这里提到了 lxml ,因为我觉得你很容易理解。您甚至可以检查其他库/包下的__init__.py文件。每个人都有自己的方式来定义子模块的路径。

      如果您尝试导入目录外的模块。然后,您必须导出模块路径,以便其他模块可以将它们找到环境变量中。这可以通过将基础目录的绝对路径附加到 PYTHONPATH 路径 来直接完成。

      了解更多:

      1. PATH variables in OS
      2. PYTHONPATH variable
      3. 因此,要解决您的问题,请在 proj-dir 下的__init__.py文件中包含所有子模块的路径,然后添加 / absolute / path / to / proj-dir PYTHONPATHPATH

        希望答案能够解释您对__init__.py的使用并解决您的问题。

答案 3 :(得分:1)

在Linux上,您只需将src目录的父文件夹的路径添加到~/.local/lib/python3.6/site-packages/my_modules.pth即可。看到 Using .pth files。然后,您可以从系统的任何位置导入src中的模块。

NB1:将python3.6替换为您要使用的任何版本的Python。

NB2:如果您使用Python2.7(不了解其他版本),则需要在__init__.pysrc/中创建src/utils(空)文件。

NB3:任何名称.pth文件都可以用于my_modules.pth

答案 4 :(得分:0)

是的,您只能从已安装的软件包或工作目录或子目录中的文件中导入代码。

答案 5 :(得分:0)

我看到它的方式,如果你安装了你的模块或软件包,你的问题就会解决,就像安装一个安装的另一个软件包然后导入(numpy,xml,json等)。

我还有一个我经常在我的所有项目中使用的软件包ulitilies,我知道导入很麻烦。

这里有一个关于如何打包python应用程序以使其可以进行pip安装的描述: https://marthall.github.io/blog/how-to-package-a-python-app/

答案 6 :(得分:0)

  • 导航到您的python安装文件夹

  • 导航到lib

  • 导航到site-packages

  • 制作名为any_thing_you_want.pth

  • 的新文件
  • 使用您喜欢的文本编辑器在该文件中键入.../src/utils/helpers.py

注意:scr/utils/helpers.py之前的省略号类似于:C:/Users/blahblahblah/python_folders/scr... < - 您需要这样做!

这是一种廉价的出路,但它保持代码清洁,并且是最不复杂的。缺点是,对于您的模块所在的每个文件夹,example.pth都需要它们。好处:与Windows一起使用到Windows 10