繁体   English   中英

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

[英]Python 3: importing a function from a python file in a parent directory

我是单元测试的新手,我正在尝试在 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 的父目录,我试图导入到 test_first_project 的模块/函数.py 文件在测试子目录中)。 我一直在运行python tests/test_first_project.py

我很快发现我不能使用诸如“from .. import first_project”或“from .. import 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 在特定目录中查找名为“first_project”的模块,即 test_first_project.py 文件的父目录。 我查看了关于模块搜索路径的部分, https://docs.python.org/3/tutorial/modules.html#the-module-search-path

当导入名为 spam 的模块时,解释器首先搜索具有该名称的内置模块。 如果未找到,它将在变量 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 上看到了关于尝试在不同目录和其他情况下导入文件的其他问题和帖子,但是模仿这些问题的语法并没有帮助我,我想我在这上面花了太多时间。 我也确信我不是唯一一个想要创建单元测试并被导入语句、模块和包问题所困扰的人。

您应该为您的项目适当地设置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以自动执行此路径设置。 当您的项目继续增长时,我建议在基本目录中有两个单独的目录 - 一个用于项目本身,另一个用于测试。 然后分别在每个中使用相对导入 如果您选择打包或将其用作子模块或类似的东西,这将使您的项目变得灵活。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM