跨目录导入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
额外注意事项
db目录下的空__init__.py无需修改,保持原样即可。- 若使用Flask框架,建议从项目根目录启动应用,利用框架的模块加载机制自动处理路径问题。
内容的提问来源于stack exchange,提问作者Tucker
相关产品推荐
相关产品推荐

