You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python封装函数跨目录导入父目录模块报NameError如何解决

问题背景

当前使用Python 3.9版本,项目目录结构如下:

parent_folder
      |
      |--> useful_functions.py
      |--> script_folder_1
                  |
                  |--> script_1.py
                  |--> function_import.py
      |--> script_folder_2
                  |
                  |--> script_2.py
                  |--> function_import.py

script_1.py与script_2.py逻辑相似但不完全相同,二者均需要调用useful_functions.py中存储的工具函数。
已验证在两个脚本顶部添加如下代码,即可正常导入useful_functions.py的函数,支持通过uf.function_name(arguments)的形式调用:

import sys
import os
local_dir = os.getcwd()
dir_up = os.path.dirname(local_dir)
sys.path.append(dir_up)
import useful_functions as uf

由于上述代码块在两个脚本中完全一致,希望将其抽离封装为独立函数存放在function_import.py中,后续若需修改导入逻辑,仅需调整单份文件再复制到另一目录即可,减少重复维护成本。
实际测试出现异常:function_import.py内的函数可在自身作用域内正常访问useful_functions.py的函数,但是调用该导入函数的脚本无法访问到相关内容,具体测试代码如下:
function_import.py内容:

def function_import():
         import sys
         import os
         import re
         local_dir = os.getcwd()
         dir_up = os.path.dirname(local_dir)
         sys.path.append(dir_up)
 
         import useful_functions as uf
         print(uf.test_function())

script_1.py内容:

import function_import
function_import.function_import()
uf.test_function()

终端运行script_1.py时,function_import()内部调用uf.test_function()可正常返回占位值3,但script_1.py中直接调用uf.test_function()会抛出异常:NameError: name 'uf' is not defined。


解决方案

方案1:适配抽离需求的实现方式

报错核心原因是Python的作用域规则:函数内部import的模块属于函数局部命名空间,调用方的全局命名空间默认无法获取该变量。如果要复用导入逻辑,最简洁无副作用的写法是让导入函数返回模块对象,由调用方接收即可。
注意:原写法用os.getcwd()取路径存在隐患,工作目录随执行命令的位置变化会导致导入失效,基于当前文件的__file__属性取路径更稳定
修改function_import.py:

import sys
import os

def import_uf():
    current_file_path = os.path.abspath(__file__)
    current_dir = os.path.dirname(current_file_path)
    parent_dir = os.path.dirname(current_dir)
    if parent_dir not in sys.path:
        sys.path.append(parent_dir)
    import useful_functions as uf
    return uf

在script_1.py/script_2.py中调用:

from function_import import import_uf
uf = import_uf()

# 后续可正常调用工具函数
uf.test_function()

如果需要实现调用函数后无需手动赋值就能直接使用uf,可以通过栈帧显式修改调用方的全局命名空间(不推荐这种隐式注入的写法,仅作参考):

# function_import.py 写法
import sys
import os
import inspect

def function_import():
    current_file_path = os.path.abspath(__file__)
    current_dir = os.path.dirname(current_file_path)
    parent_dir = os.path.dirname(current_dir)
    if parent_dir not in sys.path:
        sys.path.append(parent_dir)
    import useful_functions as uf
    caller_frame = inspect.currentframe().f_back
    caller_frame.f_globals['uf'] = uf

调用方直接执行函数即可使用:

import function_import
function_import.function_import()
uf.test_function() # 可正常运行

方案2:规范的项目级实现(长期使用推荐)

手动修改sys.path属于临时适配方案,正规Python项目不需要做路径拼接,只要将目录标记为Python包,使用标准绝对导入即可,步骤如下:

  • 在parent_folder、script_folder_1、script_folder_2三个目录下分别新建空的__init__.py文件,标记这些目录为Python可识别的包
  • 任意脚本需要导入工具函数时,直接写固定导入语句即可,不需要处理路径:
from parent_folder import useful_functions as uf
  • 执行子目录下的脚本时,在parent_folder的上级目录用-m参数以模块模式运行即可,例如执行script_1.py的命令:
python -m parent_folder.script_folder_1.script_1

这种写法不需要维护重复的路径拼接逻辑,也不会出现作用域冲突问题,是Python官方推荐的包导入方式,后续项目规模扩大也不会出现导入混乱的问题。


内容的提问来源于stack exchange,提问作者James Minor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 23:06:22