# submodule-demo **Repository Path**: tongstyle/submodule-demo ## Basic Information - **Project Name**: submodule-demo - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-06-12 - **Last Updated**: 2025-06-12 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## 作为 Git Submodule 的导入问题分析 你提出了一个很好的问题。当这个项目作为 git submodule 被其他项目引入时,使用绝对导入路径确实会产生问题,因为导入路径会基于主项目的根目录,而不是 submodule 的根目录。 ### 问题 如果你将当前项目作为 submodule 添加到另一个项目中,例如: ``` 主项目/ ├── 其他文件和目录/ └── submodule-demo/ (作为submodule) ├── common/ ├── config/ └── user/ ``` 当你在主项目中执行 `python -m submodule-demo.user.query_user 2` 时,绝对导入 `from common.mysql_operate import MySQLDatabase` 会尝试从主项目的根目录查找 `common` 模块,而不是从 submodule-demo 目录查找,这会导致导入失败。 ### 解决方案 有几种方法可以解决这个问题: 1. **使用相对于包的导入** 修改导入语句,使用相对于当前包的导入,但需要调整运行方式: ```python:d:\workspace\PycharmProjects\submodule-demo\user\query_user.py from ..common.mysql_operate import MySQLDatabase from ..config.mysql_config import DB_CONFIG import sys // ... existing code ... ``` 然后通过包的方式运行,而不是直接运行模块: ```bash python -m submodule-demo.user.query_user 2 ``` 2. **使用动态导入路径** 更灵活的方法是修改导入逻辑,使其能够适应不同的项目结构: ```python:d:\workspace\PycharmProjects\submodule-demo\user\query_user.py import sys import os # 动态确定导入路径 try: # 尝试相对导入(作为子模块使用时) from ..common.mysql_operate import MySQLDatabase from ..config.mysql_config import DB_CONFIG except ImportError: # 尝试绝对导入(直接运行时) from common.mysql_operate import MySQLDatabase from config.mysql_config import DB_CONFIG def main(arg_id): # 初始化数据库连接 db = MySQLDatabase(DB_CONFIG) # 查询操作示例 users = db.execute_query(f"SELECT * FROM tb_user where id = {arg_id}") print("用户:") for user in users: print(user) # 关闭连接 db.close() if __name__ == "__main__": arg_id = sys.argv[1] main(arg_id) ``` 3. **使用包级别的导入重定向** 在 user 包的`__init__.py`中设置导入路径,确保无论如何运行都能找到正确的模块。 ### 最佳实践 对于作为 submodule 的 Python 项目,建议: 1. 在项目根目录创建一个`setup.py`文件,使项目可以作为包安装 2. 使用相对导入处理内部模块关系 3. 提供清晰的文档说明如何在不同环境下使用该模块 这样可以确保你的代码在作为独立项目运行和作为 submodule 被引入时都能正常工作。 我需要查看当前的 user_mysql_operate.py 文件内容,然后修改它以返回标准的 JSON 格式,这样可以使用 json.loads 加载。 toolName: view_files status: success filePath: d:\workspace\PycharmProjects\main-module\user\user_mysql_operate.py 我需要查看 submodule_demo 下的 query_user.py 文件,了解它的输出格式,以便修改它来输出标准的 JSON 格式。 toolName: view_files status: success filePath: d:\workspace\PycharmProjects\main-module\submodule_demo\user\query_user.py 我将修改两个文件,使 query_user.py 输出标准 JSON 格式,并让 user_mysql_operate.py 能够正确解析这个 JSON。 ### 1. 首先修改 submodule_demo/user/query_user.py ```python:d:\workspace\PycharmProjects\main-module\submodule_demo\user\query_user.py from ..common.mysql_operate import MySQLDatabase from ..config.mysql_config import DB_CONFIG import sys import json def main(arg_id): # 初始化数据库连接 db = MySQLDatabase(DB_CONFIG) # 查询操作示例 users = db.execute_query(f"SELECT * FROM tb_user where id = {arg_id}") # 将查询结果转换为可序列化的字典列表 serializable_users = [] for user in users: # 将每个用户记录转换为普通字典 user_dict = dict(user) serializable_users.append(user_dict) # 输出标准JSON格式 result = { "data": serializable_users, "code": 200, "message": "success" } # 打印JSON字符串 print(json.dumps(result)) # 关闭连接 db.close() if __name__ == "__main__": arg_id = sys.argv[1] main(arg_id) ``` ### 2. 然后修改 user/user_mysql_operate.py ```python:d:\workspace\PycharmProjects\main-module\user\user_mysql_operate.py import subprocess import json import os def query_user_by(id:int): print(f'id:{id}') try: # 设置环境变量强制使用UTF-8编码(解决编码问题) my_env = os.environ.copy() my_env["PYTHONIOENCODING"] = "utf-8" # 调用submodule_demo下的query_user.py result = subprocess.run( ["python", "-m", "submodule_demo.user.query_user", str(id)], capture_output=True, text=True, check=True, env=my_env # 使用修改后的环境变量 ) # 尝试解析JSON输出 try: json_output = result.stdout.strip() print("子模块JSON输出:") print(json_output) # 解析JSON parsed_data = json.loads(json_output) # 返回解析后的数据 return parsed_data except json.JSONDecodeError as je: print(f"JSON解析错误: {je}") return { "data": None, "code": 400, "message": f"JSON解析错误: {je}" } except subprocess.CalledProcessError as e: print(f"执行子模块时出错: {e}") print(f"错误输出: {e.stderr}") return { "data": None, "code": 500, "message": f"执行子模块失败: {e.stderr}" } ``` ### 说明 1. **query_user.py 的修改**: - 导入 json 模块 - 将查询结果转换为可序列化的字典列表 - 构建标准的 JSON 响应格式 - 使用 json.dumps()输出标准 JSON 字符串 2. **user_mysql_operate.py 的修改**: - 添加 os 模块导入 - 设置环境变量解决编码问题 - 添加 JSON 解析逻辑 - 处理 JSON 解析错误 - 直接返回解析后的数据 这样修改后,当你调用 user_mysql_operate.py 中的 query_user_by 函数时,它会: 1. 调用 submodule_demo 中的 query_user.py 2. query_user.py 会输出标准 JSON 格式的数据 3. user_mysql_operate.py 会解析这个 JSON 并返回结构化数据 这样你就可以在 FastAPI 或其他地方直接使用这个结构化数据了。