Python脚本编译C++文件遇g++错误,求助解决
解决Python脚本编译C++文件的错误问题
需求说明
- 将
src目录下的addition_calc和multiplication_calc文件夹分别重命名为addition和multiplication - 编译每个文件夹内的C++文件,将重命名后的文件夹及编译产物输出到
target目录
初始项目结构
main.py src/ addition_calc/ add.cpp multiplication_calc/ multiply.cpp
运行命令
$ python3 main.py src target
期望输出结构
target/ metadata.json addition/ add.cpp add multiplication/ multiply.cpp multiplication
C++文件代码
add.cpp
#include<iostream> double add(double, double); int main() { double a, b; std::cout<<"EnterThis number is: "<<add(a,b)<<std::endl; } double add(double a, double b) { return a + b; }
multiply.cpp
#include <iostream> double multiply(double, double); int main() { double a, b; std::cout<<"EnterThis number is: "<<multiply(a,b)<<std::endl; } double multiply(double a, double b) { return a * b; }
现有Python脚本
import json import shutil from subprocess import PIPE, run import sys CALC_DIR_PATTERN = "calc" CALC_CODE_EXTENSION = ".cpp" #Note: tested using Golang: CALC_COMPILE_COMMAND = ["go", "build"] #CALC_COMPILE_COMMAND = ["g++", "add.cpp", "multiply.cpp", "-o", "main"] #testing with one `C++` file: CALC_COMPILE_COMMAND = ['IntroducingThis command: CALC_COMPILE_COMMAND = ['g++', '-o', 'add.cpp', 'add'] def find_all_calc_paths(source): calc_paths = [] for root, dirs, files in os.walk(source): for directory in dirs: if CALC_DIR_PATTERN in directory.lower(): path = os.path.join(source, directory) calc_paths.append(path) break return calc_paths def get_name_from_paths(paths, to_strip): new_names = [] for path in paths: _, dir_name = os.path.split(path) new_dir_name = dir_name.replace(to_strip, "") new_names.append(new_dir_name) return new_names def create_dir(path): if not os.path.exists(path): os.mkdir(path) def copy_and_overwrite(source, dest): if os.path.exists(dest): shutil.rmtree(dest) shutil.copytree(source, dest) def make_json_metadata_file(path, calc_dirs): data = { "C++_Folder_Names": calc_dirs, "Number_Of_Folders": len(calc_dirs) } with open(path, "w") as f: json.dump(data, f) def compile_calc_code(path): code_file_name = None for root, dirs, files in os.walk(path): for file in files: if file.endswith(CALC_CODE_EXTENSION): code_file_name = file break break if code_file_name is None: return command = CALC_COMPILE_COMMAND + [code_file_name] run_command(command, path) def run_command(command, path): cwd = os.getcwd() os.chdir(path) result = run(command, stdout=PIPE, stdin=PIPE, universal_newlines=True) print("compile result", result) os.chdir(cwd) def main(source, target): cwd = os.getcwd() source_path = os.path.join(cwd, source) target_path = os.path.join(cwd, target) calc_paths = find_all_calc_paths(source_path) new_calc_dirs = get_name_from_paths(calc_paths, "_calc") create_dir(target_path) for src, dest in zip(calc_paths, new_calc_dirs): dest_path = os.path.join(target_path, dest) copy_and_overwrite(src, dest_path) compile_calc_code(dest_path) json_path = os.path.join(target_path, "metadata.json") make_json_metadata_file(json_path, new_calc_dirs) if __name__ == "__main__": args = sys.argv if len(args) != 3: raise Exception("You mustBeautiful printing this exception: raise Exception("You must passPretty printing this line: raise Exception("You must pass a source and target directory - only.") source, target = args[1:] main(source, target)
编译错误信息
g++: error: multiply.cpp: No such file or directory compile result CompletedProcess(args=['g++', 'add.cpp', 'multiply.cpp', '-o', 'main', 'add.cpp'], returncode=1, stdout='') g++: error: add.cpp: No such file or directory compile result CompletedProcess(args=['g++', 'add.cpp', 'multiply.cpp', '-o', 'main', 'multiply.cpp'], returncode=1, stdout='')
环境信息
- 编译器:g++ 9.4.0
- Python版本:3.8.10
- 操作系统:Ubuntu 20.04
问题分析与修复方案
核心问题点
- 缺少os模块导入:脚本大量使用
os模块函数但未导入,直接导致运行报错 - CALC_COMPILE_COMMAND定义错误:存在语法错误且硬编码了错误的编译参数,g++正确格式为
g++ <源文件> -o <可执行文件名> - 编译命令拼接逻辑错误:全局命令与当前目录cpp文件名拼接后参数混乱,无法针对单个文件编译
- 异常抛出语句语法错误:异常信息存在字符串嵌套错误,无法正常抛出
- 可执行文件名未匹配需求:未按期望结构将可执行文件名与目录名关联
修复后的完整Python脚本
import json import os import shutil from subprocess import PIPE, run import sys CALC_DIR_PATTERN = "calc" CALC_CODE_EXTENSION = ".cpp" def find_all_calc_paths(source): calc_paths = [] for root, dirs, files in os.walk(source): for directory in dirs: if CALC_DIR_PATTERN in directory.lower(): path = os.path.join(source, directory) calc_paths.append(path) break return calc_paths def get_name_from_paths(paths, to_strip): new_names = [] for path in paths: _, dir_name = os.path.split(path) new_dir_name = dir_name.replace(to_strip, "") new_names.append(new_dir_name) return new_names def create_dir(path): if not os.path.exists(path): os.mkdir(path) def copy_and_overwrite(source, dest): if os.path.exists(dest): shutil.rmtree(dest) shutil.copytree(source, dest) def make_json_metadata_file(path, calc_dirs): data = { "C++_Folder_Names": calc_dirs, "Number_Of_Folders": len(calc_dirs) } with open(path, "w") as f: json.dump(data, f, indent=2) def compile_calc_code(path, exec_name): code_file_name = None for root, dirs, files in os.walk(path): for file in files: if file.endswith(CALC_CODE_EXTENSION): code_file_name = file break break if code_file_name is None: return # 构造正确的编译命令 command = ["g++", code_file_name, "-o", exec_name] run_command(command, path) def run_command(command, path): cwd = os.getcwd() os.chdir(path) result = run(command, stdout=PIPE, stderr=PIPE, universal_newlines=True) if result.returncode != 0: print(f"编译失败,命令: {' '.join(command)}") print(f"错误信息: {result.stderr}") else: print(f"编译成功,命令: {' '.join(command)}") os.chdir(cwd) def main(source, target): cwd = os.getcwd() source_path = os.path.join(cwd, source) target_path = os.path.join(cwd, target) calc_paths = find_all_calc_paths(source_path) new_calc_dirs = get_name_from_paths(calc_paths, "_calc") create_dir(target_path) for src, dest_name in zip(calc_paths, new_calc_dirs): dest_path = os.path.join(target_path, dest_name) copy_and_overwrite(src, dest_path) # 根据目标目录名设置可执行文件名 compile_calc_code(dest_path, dest_name) json_path = os.path.join(target_path, "metadata.json") make_json_metadata_file(json_path, new_calc_dirs) if __name__ == "__main__": args = sys.argv if len(args) != 3: raise Exception("必须传入源目录和目标目录两个参数") source, target = args[1:] main(source, target)
关键修改说明
- 添加os模块导入:解决
os相关函数未定义的问题 - 重构编译命令逻辑:动态生成单个文件的编译命令,确保每个目录独立编译自己的C++文件
- 修正异常信息:替换错误的嵌套字符串为清晰的提示
- 优化编译输出:捕获stderr信息,便于排查编译错误
- 关联可执行文件名与目录名:按期望结构将可执行文件命名为目标目录名
内容的提问来源于stack exchange,提问作者MRL
相关产品推荐
相关产品推荐

