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

跨目录导入Python MySQL连接函数遇ModuleNotFoundError求助

问题描述

正在将SQLite数据库迁移至MySQL,希望在/app/app.py中调用/db/connect.py内的sql_db_connection()函数实现MySQL连接共享。用/app/test.py测试导入时,即使在/db目录添加了空__init__.py文件,仍出现ModuleNotFoundError,但/db/connect.py单独运行正常。已尝试多篇技术教程及同类问题解决方案,均未解决。

已尝试方案

  • 研究Python跨目录导入模块的方法
  • 参考Flask跨文件使用MySQL连接的方案
  • 查阅Python绝对/相对导入的官方文档
  • 学习Python跨文件调用函数的实现方式

测试代码(/app/test.py)

from db.connect import sql_db_connection
import db

def get_all():
    conn = sql_db_connection()
    cursor = conn.cursor()
    cursor.execute("select * from posts")
    result = cursor.fetchall()
    for x in result:
        print(x)

报错信息

Traceback (most recent call last):
  File "/Users/<uname>/<my-long-app-name>/app/test.py", line 1, in <module>
    from db.connect import sql_db_connection
ModuleNotFoundError: No module named 'db'

MySQL连接代码(/db/connect.py)

import sshtunnel
import MySQLdb
import os
from dotenv import load_dotenv

# Load all env vars
load_dotenv()

def sql_db_connection():
    sshtunnel.SSH_TIMEOUT = 5.0
    sshtunnel.TUNNEL_TIMEOUT = 5.0

    with sshtunnel.SSHTunnelForwarder(
        ('ssh.pythonanywhere.com'),
        ssh_username=os.getenv("REMOTE_DB_SSH_USERNAME"), ssh_password=os.getenv("REMOTE_SSH_PASSWORD"),
        remote_bind_address=(
            os.getenv("REMOTE_BIND_ADDRESS"), 3306)
    ) as tunnel:
        conn = MySQLdb.connect(
            user=os.getenv("REMOTE_DB_SSH_USERNAME"),
            passwd=os.getenv("REMOTE_DB_PASSWORD"),
            host='0.0.0.0', port=tunnel.local_bind_port,
            db=os.getenv("REMOTE_DB_NAME"),
        )
        print('Connected!')
        
        return conn

sql_db_connection()

项目目录结构

.
├── Dockerfile
├── README.md
├── __pycache__
│   ├── app.cpython-310.pyc
│   ├── app.cpython-39.pyc
│   ├── config.cpython-39.pyc
│   ├── wsgi.cpython-38.pyc
│   └── wsgi.cpython-39.pyc
├── app
│   ├── Dockerfile
│   ├── __init__.py
│   ├── __pycache__
│   ├── app.py
│   ├── config.py
│   ├── public
│   ├── requirements.txt
│   ├── templates
│   ├── test.py
│   └── wsgi.py
├── db
│   ├── Dockerfile
│   ├── README.md
│   ├── __init__.py
│   ├── __pycache__
│   ├── connect.py
│   ├── database.db
│   ├── dump.sql
│   ├── init_db.py
│   ├── mysql_dump.sql
│   ├── schema.sql
│   └── schema_mysql.sql
├── docker-compose.yml
├── features.md
├── images
├── requirements.txt
├── setup.py
├── venv
│   ├── bin
│   ├── include
│   ├── lib
│   ├── man
│   └── pyvenv.cfg
└── wsgi.py

解决方案

问题核心是Python解释器默认的模块搜索路径不包含项目根目录,导致找不到db模块。以下是三种可行解决方法:

方法一:使用相对导入

app和db是同级目录,修改test.py的导入语句为相对导入(注意:需从项目根目录执行python -m app.test,不能直接运行test.py):

from ..db.connect import sql_db_connection

def get_all():
    conn = sql_db_connection()
    cursor = conn.cursor()
    cursor.execute("select * from posts")
    result = cursor.fetchall()
    for x in result:
        print(x)

方法二:手动添加项目根目录到搜索路径

在test.py开头添加代码,将项目根目录加入Python的模块搜索路径:

import sys
import os
# 获取项目根目录(当前文件所在目录的父目录)
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

from db.connect import sql_db_connection

def get_all():
    conn = sql_db_connection()
    cursor = conn.cursor()
    cursor.execute("select * from posts")
    result = cursor.fetchall()
    for x in result:
        print(x)

修改后可直接运行test.py。

方法三:设置环境变量

运行test.py前,将项目根目录添加到PYTHONPATH环境变量:

  • macOS/Linux:
export PYTHONPATH=/Users/<uname>/<my-long-app-name>
python app/test.py
  • Windows(PowerShell):
$env:PYTHONPATH="C:\path\to\<my-long-app-name>"
python app/test.py

额外注意事项

  1. db目录下的空__init__.py无需修改,保持原样即可。
  2. 若使用Flask框架,建议从项目根目录启动应用,利用框架的模块加载机制自动处理路径问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 22:40:17