Python 3:从父目录中的python文件导入函数

时间:2019-04-14 19:58:40

标签: python python-3.x

我是单元测试的新手,我正尝试在python 3中创建我的第一个单元测试文件。因此,仅从模仿在线课程开始,我就拥有以下真正的基本文件夹结构。

D:\Projects\Projects\unit_testing_course  # parent dir absolute path

unit_testing_course/                      # root/parent folder
    first_project.py                      # has a function called avg() 
    tests/                                
        test_first_project.py             # I want to import avg() into this file

test_first_project.py是我用于单元测试的文件,我想从存在于其上方父目录中的first_project.py导入avg()函数。

我在Windows 10上,我将git bash打开到以下路径:'/ d / Projects / Projects / unit_testing_course'(即,包含first_project.py的父目录,我正在尝试导入的模块/函数到tests子目录中的test_first_project.py文件)。我继续运行python tests/test_first_project.py

我很快发现我无法使用类似 “从..导入first_project”或“从..导入avg”,这会导致“ ValueError:尝试相对导入到顶级程序包之外”错误消息。

因此,通过阅读文档,我发现“ from”和“ import”都是用于模块或软件包的说明。 https://docs.python.org/3/tutorial/modules.html

  

“ Python可以将定义放入文件中,并在   脚本或解释器的交互式实例。这样的文件   被称为模块;可以将模块中的定义导入到   其他模块或进入主模块(变量的集合   您可以在顶层和   计算器模式)。

     

模块是一个包含Python定义和语句的文件。的   文件名是模块名称,后缀.py。在一个   模块,模块名称(作为字符串)可以作为   全局变量__name __。”

所以听起来就python 3而言,每个.py文件都是一个模块,模块名称本质上是.py文件名,结尾没有.py扩展名。听起来我正在尝试从test_first_project.py文件的父目录导入模块。

该文档链接似乎有助于说明以下情况:在当前目录中有一个模块,您将从中执行程序/ python shell,而您只是试图将功能从该模块导入该程序。

但是在这种情况下,似乎我们实际上需要告诉python在特定目录(即test_first_project.py文件的父目录)内查找名为“ first_project”的模块。我看了关于模块搜索路径的部分,https://docs.python.org/3/tutorial/modules.html#the-module-search-path

  

导入名为垃圾邮件的模块时,解释器首先搜索具有该名称的内置模块。如果找不到,它将在变量sys.path给出的目录列表中搜索名为spam.py的文件。   初始化后,Python程序可以修改sys.path。包含正在运行的脚本的目录位于搜索路径的开始,在标准库路径之前。

然后我尝试了...

import sys
import os
p_dir_path = os.path.abspath('../')
sys.path.append(p_dir_path)
from  first_project import avg

还有哪些错误消息“ ValueError:尝试相对顶级包进行相对导入”。我希望以编程方式修改sys.path可以改变事情...

那么,为了从父目录导入模块,我实际上需要做什么? 或者...不可能在python中这样做吗?我是否需要使用软件包而不是模块(即是否需要在父目录中创建 init .py)?

我在stackoverflow上看到过其他问题和有关尝试在其他目录中导入文件的帖子和其他情况,但是模仿这些问题的语法并没有帮助我,我认为我花了太多时间在此。我还可以肯定,我不是唯一一个想要创建单元测试并且被导入语句,模块和包的问题所困扰的人。

1 个答案:

答案 0 :(得分:1)

您应该为您的项目适当地设置PYTHONPATH变量。在unit_testing_course中,运行

export PYTHONPATH=$(pwd)

在您的外壳中。并考虑以下代码:

first_project.py

def avg(l):
    return sum(l)/len(l) if len(l) > 0 else 0

tests/test_first_project.py

import unittest 
from first_project import avg

class Test(unittest.TestCase):
    ...

tests/__init__.py

from .test_first_project import *

运行python -m unittest tests将根据需要运行(提供的python指向您所需的python版本)。您还可以使用virtualenv并修改其venv/bin/activate以自动执行此路径设置。当您的项目继续增长时,我建议在基础中有两个单独的目录-一个用于项目本身,一个用于测试。然后分别使用 relative imports 。如果您选择package或将其用作submodule或类似的东西,这将使您的项目更加灵活。