使用cx_Freeze打包含subprocess的Python脚本时遇FileNotFoundError求助
问题描述
我编写了一个从.p12文件提取公钥的Python脚本,在Spyder中运行正常,但使用cx_Freeze打包为可执行文件后,运行时出现FileNotFoundError: [WinError 2] Das System kann die angegebene Datei nicht finden错误。
提取公钥的脚本代码(extract_pubkey.py)
import os import pandas as pd import subprocess def extract_public_key_from_p12_and_match_password(excel_file_path, p12_folder, output_folder): excel_data = pd.read_excel(excel_file_path) p12_files = [file for file in os.listdir(p12_folder) if file.endswith('.p12')] if not os.path.exists(output_folder): os.makedirs(output_folder) for p12_file in p12_files: email = p12_file.split('_')[1].replace('-', '.') password = excel_data.loc[excel_data['Email'] == email, 'Password'].values if len(password) == 0: print(f"Password not found {email}") continue password = password[0] input_path = os.path.join(p12_folder, p12_file) output_path = os.path.join(output_folder, f'{p12_file.replace(".p12", "_pubkey.pem")}') command = ['openssl', 'pkcs12', '-in', input_path, '-clcerts', '-nokeys', '-out', output_path, '-passin', f'pass:{password}'] subprocess.Popen(command) print(f"Public key saved {email}.") excel_file_path = r'.\myfile.xlsx' p12_folder = r'.\p12-folder' output_folder = r'.\pubcert-folder' extract_public_key_from_p12_and_match_password(excel_file_path, p12_folder, output_folder)
cx_Freeze打包配置(setup.py)
import sys import os.path from cx_Freeze import setup, Executable main_script = 'extract_pubkey.py' executables = [Executable(main_script, base = None)] build_exe_options = { "packages": ['subprocess', 'os', 'pandas', 'pip', 'cryptography'], } setup( name = 'name', version = '0.1', options={"build_exe": build_exe_options}, executables = executables )
运行exe时的错误信息
Traceback (most recent call last): File "C:\Users\MyUser\Desktop\...\venv_pubcert\Lib\site-packages\cx_Freeze\initscripts\__startup__.py", line 124, in run module_init.run(name + "__main__") File "C:\Users\MyUser\Desktop\...\venv_pubcert\Lib\site-packages\cx_Freeze\initscripts\console.py", line 16, in run exec(code, module_main.__dict__) File "extract_pubkey.py", line 53, in <module> File "extract_pubkey.py", line 44, in extract_public_key_from_p12_and_match_password File "C:\Users\MyUser\anaconda3\lib\subprocess.py", line 858, in __init__ self._execute_child(args, executable, preexec_fn, close_fds, File "C:\Users\MyUser\anaconda3\lib\subprocess.py", line 1311, in _execute_child hp, ht, pid, tid = _winapi.CreateProcess(executable, args, FileNotFoundError: [WinError 2] Das System kann die angegebene Datei nicht finden
解决方案
错误核心是打包后的可执行文件找不到openssl命令,以下是三种可行解决思路:
1. 直接指定openssl完整路径
修改脚本中调用openssl的部分,替换为系统中openssl可执行文件的绝对路径:
# 替换为你本地openssl的实际安装路径 openssl_path = r'C:\Program Files\OpenSSL-win64\bin\openssl.exe' command = [openssl_path, 'pkcs12', '-in', input_path, '-clcerts', '-nokeys', '-out', output_path, '-passin', f'pass:{password}']
2. 将openssl文件打包到输出目录
- 找到openssl安装目录下的
openssl.exe及依赖dll文件(如libcrypto-1_1-x64.dll、libssl-1_1-x64.dll) - 修改setup.py,添加
include_files参数将这些文件打包:
build_exe_options = { "packages": ['subprocess', 'os', 'pandas', 'pip', 'cryptography'], "include_files": [ r'C:\Program Files\OpenSSL-win64\bin\openssl.exe', r'C:\Program Files\OpenSSL-win64\bin\libcrypto-1_1-x64.dll', r'C:\Program Files\OpenSSL-win64\bin\libssl-1_1-x64.dll' ] }
- 同时修改脚本,动态获取打包后的openssl路径:
import sys # 判断是否为打包后的运行环境 if getattr(sys, 'frozen', False): openssl_path = os.path.join(sys._MEIPASS, 'openssl.exe') else: openssl_path = 'openssl' command = [openssl_path, 'pkcs12', '-in', input_path, '-clcerts', '-nokeys', '-out', output_path, '-passin', f'pass:{password}']
3. 使用Python库替代openssl命令行
用cryptography库直接处理p12文件,彻底避免依赖外部命令,是最稳定的方案:
import os import pandas as pd from cryptography.hazmat.primitives import serialization from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives.serialization import pkcs12 def extract_public_key_from_p12_and_match_password(excel_file_path, p12_folder, output_folder): excel_data = pd.read_excel(excel_file_path) p12_files = [file for file in os.listdir(p12_folder) if file.endswith('.p12')] if not os.path.exists(output_folder): os.makedirs(output_folder) for p12_file in p12_files: email = p12_file.split('_')[1].replace('-', '.') password = excel_data.loc[excel_data['Email'] == email, 'Password'].values if len(password) == 0: print(f"Password not found {email}") continue password = password[0].encode('utf-8') input_path = os.path.join(p12_folder, p12_file) output_path = os.path.join(output_folder, f'{p12_file.replace(".p12", "_pubkey.pem")}') # 读取p12文件 with open(input_path, 'rb') as f: private_key, certificate, additional_certificates = pkcs12.load_key_and_certificates( f.read(), password=password, backend=default_backend() ) # 导出公钥 if certificate: public_key_pem = certificate.public_bytes( encoding=serialization.Encoding.PEM, format=serialization.PublicFormat.SubjectPublicKeyInfo ) with open(output_path, 'wb') as f: f.write(public_key_pem) print(f"Public key saved {email}.") else: print(f"No certificate found in {p12_file} for {email}") excel_file_path = r'.\myfile.xlsx' p12_folder = r'.\p12-folder' output_folder = r'.\pubcert-folder' extract_public_key_from_p12_and_match_password(excel_file_path, p12_folder, output_folder)
内容的提问来源于stack exchange,提问作者Aukru
相关产品推荐
相关产品推荐

