Python脚本作为.py文件正常运行,打包为pip包后失效如何排查?
问题:Python脚本打包为PyPI包后调用Copilot CLI生成空输出
本地直接运行.py脚本时,可正常调用Copilot CLI生成COBOL文档;但打包成pip包后,输出文件为空且生成速度异常快。已确认copilot命令可被程序找到,无法定位具体故障原因。
脚本代码
import argparse as ap import os import sys import subprocess import shutil from subprocess import PIPE from tqdm import tqdm # Main function def main(): # Parse command line arguments parser = ap.ArgumentParser(description="Automate COBOL documentation generation using Copilot.") parser.add_argument("-p","--Prompt",type=str,help="Prompt directory for Copilot to generate documentation.") parser.add_argument("-c","--Cobol",type=str,help="COBOL source code directory OR File to be documented.") parser.add_argument("-o","--Output",type=str,help="Output directory for generated documentation.") args = parser.parse_args() # Create variables for paths and validate them prompt_path = args.Prompt cobol_path = args.Cobol output_path = args.Output if not os.path.exists(prompt_path): print(f"Error: Prompt path '{prompt_path}' does not exist.") sys.exit(1) if not os.path.exists(cobol_path): print(f"Error: COBOL path '{cobol_path}' does not exist.") sys.exit(1) if output_path is None: output_path = os.path.join(os.getcwd(), "Cobol_Documentation_Output") print(f"No output path provided. Using default: '{output_path}'") if not os.path.exists(output_path): os.makedirs(output_path) print(f"Created output directory at '{output_path}'.") # Finally check if we can find the copilot command and run it if shutil.which("copilot") is None: print("Error: 'copilot' command not found. Please ensure Copilot is installed and in your PATH.") sys.exit(1) print("Validation steps completed successfully. Moving to documentation generation...") # PROCESS SINGLE FILE ELSE DIRECTORY if os.path.isfile(cobol_path): print("Processing single COBOL file...") process_cobol_file(cobol_path, prompt_path, output_path) else: # First, collect all COBOL files to get total count cobol_files = [] for root, _, files in os.walk(cobol_path): for file in files: if file.lower().endswith(".cbl") or file.lower().endswith(".cob"): cobol_file_path = os.path.join(root, file) cobol_files.append(cobol_file_path) if not cobol_files: print(f"No COBOL files found in '{cobol_path}'.") return print(f"Found {len(cobol_files)} COBOL file(s) to process...") # Process files with progress bar for cobol_file_path in tqdm(cobol_files, desc="Processing COBOL files", unit="file"): process_cobol_file(cobol_file_path, prompt_path, output_path) print("Documentation generation completed.") def process_cobol_file(cobol_file_path, prompt_path, output_path): # Get base filename for cleaner progress display file_name = os.path.basename(cobol_file_path) # Grab our prompts prompt_files = [file for file in os.listdir(prompt_path) if file.endswith(".txt")] if not prompt_files: print(f"No prompt files found in '{prompt_path}'. Skipping file.") return # Process each prompt file with progress bar for prompt_file in tqdm(prompt_files, desc=f"Processing {file_name}", unit="prompt", leave=False): prompt_file_path = os.path.join(prompt_path, prompt_file) with open(prompt_file_path, 'r') as pf: prompt_content = pf.read() final_prompt = f"{prompt_content}. Please generate documentation for the following COBOL code:{cobol_file_path}" # Construct the copilot command command = shutil.which("copilot") print(command) cmd = [command, "-p", final_prompt, "--allow-all-tools"] # Execute the command process = subprocess.Popen(cmd, stdout=PIPE, stderr=PIPE) stdout, stderr = process.communicate() # write the output to the output file output_file_name = f"{os.path.basename(cobol_file_path)}_{os.path.splitext(prompt_file)[0]}_documentation.txt" output_file_path = os.path.join(output_path, output_file_name) with open(output_file_path, 'wb') as out_file: out_file.write(stdout) if process.returncode != 0: tqdm.write(f"Error generating documentation for '{cobol_file_path}' with prompt '{prompt_file}': {stderr.decode()}") else: tqdm.write(f"Successfully generated documentation for '{file_name}' with prompt '{prompt_file}'.") if __name__ == "__main__": main()
setup.py构建脚本
from setuptools import setup setup( name="mts-gendoc-cobol", version="1.0.4", description="Generate COBOL documentation using Copilot", author="Ben Bastianelli", author_email="benbastianelli@gmail.com", packages=["gendoc"], entry_points={ 'console_scripts': [ 'gen-doc=gendoc.__main__:main' ] }, classifiers=[ "Programming Language :: Python :: 3", "Operating System :: OS Independent", ], python_requires='>=3.6', )
打包部署命令
# 打包命令 python .\set_up.py sdist bdist_wheel twine upload dist/* # 安装步骤 pip install mts-gendoc-cobol # 使用方式 gen-doc -p PROMPT_DIR -c COBOL_CONTEXT -o OUT
排查方向及解决建议
环境变量传递问题
本地脚本继承当前Shell的环境变量,而pip包作为console_script运行时,环境变量可能受限。Copilot CLI可能依赖API密钥、配置路径等未正确传递的变量。- 解决:调用
subprocess.Popen时添加env=os.environ.copy()参数,显式传递完整环境变量。
- 解决:调用
命令参数解析异常
打包后,过长或含特殊字符的final_prompt可能导致Copilot CLI无法正确解析。本地运行时Shell会处理参数,但console_script的参数传递逻辑存在差异。- 解决:将prompt内容写入临时文件,通过文件路径传递给Copilot CLI(若支持);或对prompt内容做转义处理。
工作目录不一致
打包后的命令运行时,工作目录可能不是用户当前目录,导致Copilot内部相对路径操作失败。- 解决:在
subprocess.Popen中添加cwd=os.getcwd()参数,显式指定子进程工作目录。
- 解决:在
错误信息未完整捕获
即使进程返回码为0,Copilot CLI可能存在静默错误导致输出为空。当前代码仅在返回码非零时打印stderr,无法排查此类情况。- 解决:无论返回码如何,都打印完整的stderr内容;同时添加超时机制(如
process.communicate(timeout=30)),避免进程提前退出或挂起。
- 解决:无论返回码如何,都打印完整的stderr内容;同时添加超时机制(如
内容的提问来源于stack exchange,提问作者ben bastianelli
相关产品推荐
相关产品推荐

