gl-py2pyd 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- gl_py2pyd-0.1.0.dist-info/METADATA +124 -0
- gl_py2pyd-0.1.0.dist-info/RECORD +9 -0
- gl_py2pyd-0.1.0.dist-info/WHEEL +5 -0
- gl_py2pyd-0.1.0.dist-info/entry_points.txt +2 -0
- gl_py2pyd-0.1.0.dist-info/top_level.txt +2 -0
- module/__init__.py +10 -0
- module/fileConversion.py +49 -0
- module/single_py2pyd.py +161 -0
- py2pyd.py +91 -0
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: gl-py2pyd
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: 将Python文件转换为pyd/so文件的工具
|
|
5
|
+
Home-page: https://github.com/yourusername/py2pyd-arg
|
|
6
|
+
Author: gu lei
|
|
7
|
+
Author-email:
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Requires-Python: >=3.6
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
Requires-Dist: cython
|
|
14
|
+
Requires-Dist: loguru
|
|
15
|
+
Dynamic: author
|
|
16
|
+
Dynamic: classifier
|
|
17
|
+
Dynamic: description
|
|
18
|
+
Dynamic: description-content-type
|
|
19
|
+
Dynamic: home-page
|
|
20
|
+
Dynamic: requires-dist
|
|
21
|
+
Dynamic: requires-python
|
|
22
|
+
Dynamic: summary
|
|
23
|
+
|
|
24
|
+
# Python转pyd/so工具
|
|
25
|
+
|
|
26
|
+
这个工具用于将Python文件(.py)转换为编译后的Python扩展模块(.pyd或.so),使用Cython进行编译。
|
|
27
|
+
|
|
28
|
+
## 功能特点
|
|
29
|
+
|
|
30
|
+
- 支持单个Python文件的转换
|
|
31
|
+
- 支持目录批量转换
|
|
32
|
+
- 支持递归处理子目录
|
|
33
|
+
- 转换后可选择是否删除原始Python文件
|
|
34
|
+
- 保留`__init__.py`文件内容处理
|
|
35
|
+
- 自动检测依赖并提供错误处理
|
|
36
|
+
- 针对不同操作系统自动选择正确的扩展名(Windows为.pyd,Linux/MacOS为.so)
|
|
37
|
+
- 优化编译选项,消除常见警告信息
|
|
38
|
+
|
|
39
|
+
## 安装依赖
|
|
40
|
+
|
|
41
|
+
在使用此工具前,请确保已安装以下依赖:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
pip install cython loguru
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
此外,你的系统需要有合适的C/C++编译器:
|
|
48
|
+
- Windows: 需要安装Visual C++ Build Tools
|
|
49
|
+
- Linux: 需要安装GCC
|
|
50
|
+
- macOS: 需要安装XCode命令行工具(`xcode-select --install`)
|
|
51
|
+
|
|
52
|
+
## 使用方法
|
|
53
|
+
|
|
54
|
+
### 1. 转换单个文件
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
python py2pyd.py path/to/your/file.py
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### 2. 转换目录下所有Python文件
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
python py2pyd.py path/to/your/directory
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### 3. 递归转换目录及其子目录中的所有Python文件
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
python py2pyd.py -r path/to/your/directory
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### 4. 转换后删除原始Python文件
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
python py2pyd.py --remove path/to/your/file.py
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### 5. 全部选项组合
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
python py2pyd.py -r --remove path/to/your/directory
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## 作为模块导入
|
|
85
|
+
|
|
86
|
+
你也可以在自己的Python代码中导入该模块:
|
|
87
|
+
|
|
88
|
+
```python
|
|
89
|
+
# 转换单个文件
|
|
90
|
+
from module.single_py2pyd import py2pyd
|
|
91
|
+
success = py2pyd('path/to/your/file.py')
|
|
92
|
+
if success:
|
|
93
|
+
print("转换成功")
|
|
94
|
+
else:
|
|
95
|
+
print("转换失败")
|
|
96
|
+
|
|
97
|
+
# 转换整个目录
|
|
98
|
+
from module.fileConversion import FileConversion
|
|
99
|
+
converter = FileConversion()
|
|
100
|
+
success = converter.get_all_file('path/to/your/directory', need_remove=False)
|
|
101
|
+
print(f"成功:{converter.success_count} 个文件,失败:{converter.fail_count} 个文件")
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## 错误处理
|
|
105
|
+
|
|
106
|
+
工具会自动检测必要的依赖并提供错误信息。常见问题包括:
|
|
107
|
+
|
|
108
|
+
1. **缺少Cython**: 运行前会检查Cython是否已安装,若未安装则会提示安装。
|
|
109
|
+
2. **编译失败**: 如果编译失败,会提供详细错误信息,可能是缺少编译器或者Python文件内容有问题。
|
|
110
|
+
|
|
111
|
+
## 优化的编译选项
|
|
112
|
+
|
|
113
|
+
本工具针对不同操作系统和环境进行了编译选项优化:
|
|
114
|
+
|
|
115
|
+
1. **设置语言级别**: 显式设置Cython的`language_level`为3,避免语言级别警告
|
|
116
|
+
2. **禁止无用代码警告**: 添加适当的编译选项(`-Wno-unreachable-code`)以禁止Cython生成的C代码中的不可达代码警告
|
|
117
|
+
3. **修复Conda/Miniconda链接警告**: 在Conda环境中自动调整链接选项,避免重复的rpath警告
|
|
118
|
+
|
|
119
|
+
## 注意事项
|
|
120
|
+
|
|
121
|
+
- 确保已安装Cython和适当的编译器
|
|
122
|
+
- 转换后的so/pyd文件会保留在原始Python文件的相同目录中
|
|
123
|
+
- 在Windows系统上生成.pyd文件,在Linux/MacOS上生成.so文件
|
|
124
|
+
- 对于复杂的Python项目,可能需要额外的编译选项
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
py2pyd.py,sha256=WBkiwqHMOhegcp0s57Zvh0i64SO3IiUgUwN4ej_lJhs,3016
|
|
2
|
+
module/__init__.py,sha256=Fh4A481uGhDkVmqGIH8MKH5_yAMncOz2UBdbCoYLl6k,220
|
|
3
|
+
module/fileConversion.py,sha256=C5N_8WkCadZFEo1ylbaGEiDoINK3lKh7bEbz_rqdu3Q,1714
|
|
4
|
+
module/single_py2pyd.py,sha256=lx1CojipLdkyJWSCsxSFHGNZPHCZKiN42Osd6Zmlktg,6048
|
|
5
|
+
gl_py2pyd-0.1.0.dist-info/METADATA,sha256=LdrkXjhVhU6W3bq6gr0F9KgRqNkgjBFUXTxL28CWv7g,3586
|
|
6
|
+
gl_py2pyd-0.1.0.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
|
7
|
+
gl_py2pyd-0.1.0.dist-info/entry_points.txt,sha256=MNnYM2S-NKXNdgYAJ6ZVbXgOpFfZ3F9aQwn8MudjjSU,39
|
|
8
|
+
gl_py2pyd-0.1.0.dist-info/top_level.txt,sha256=uPWv-HYowjiEf_u6fIT0VxVmHRAn9YF2s-ORQePa1U4,14
|
|
9
|
+
gl_py2pyd-0.1.0.dist-info/RECORD,,
|
module/__init__.py
ADDED
module/fileConversion.py
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
'''
|
|
2
|
+
Author: gu lei
|
|
3
|
+
Date: 2023-01-20 13:52:06
|
|
4
|
+
LastEditTime: 2023-09-26 10:43:03
|
|
5
|
+
LastEditors: gu lei
|
|
6
|
+
'''
|
|
7
|
+
import os
|
|
8
|
+
import time
|
|
9
|
+
from loguru import logger
|
|
10
|
+
from .single_py2pyd import py2pyd
|
|
11
|
+
|
|
12
|
+
class FileConversion:
|
|
13
|
+
|
|
14
|
+
def __init__(self) -> None:
|
|
15
|
+
self.initpy = None
|
|
16
|
+
self.success_count = 0
|
|
17
|
+
self.fail_count = 0
|
|
18
|
+
|
|
19
|
+
def get_all_file(self, path, need_remove: bool): # 遍历此目录下的所有py文件,包含子目录里的py
|
|
20
|
+
for root, dirs, files in os.walk(path):
|
|
21
|
+
if "__init__.py" in files:
|
|
22
|
+
self.process_init_py(root)
|
|
23
|
+
files.remove("__init__.py")
|
|
24
|
+
for name in files:
|
|
25
|
+
if name.endswith(".py"):
|
|
26
|
+
file_path = os.path.join(root, name)
|
|
27
|
+
success = py2pyd(file_path)
|
|
28
|
+
if success:
|
|
29
|
+
self.success_count += 1
|
|
30
|
+
if need_remove:
|
|
31
|
+
os.remove(file_path)
|
|
32
|
+
else:
|
|
33
|
+
self.fail_count += 1
|
|
34
|
+
if self.initpy:
|
|
35
|
+
self.process_init_py(root)
|
|
36
|
+
|
|
37
|
+
logger.info(f"处理完成!成功: {self.success_count} 个文件,失败: {self.fail_count} 个文件")
|
|
38
|
+
return self.success_count > 0 and self.fail_count == 0
|
|
39
|
+
|
|
40
|
+
def process_init_py(self, path):
|
|
41
|
+
init_py_path = os.path.join(path, '__init__.py')
|
|
42
|
+
if self.initpy:
|
|
43
|
+
with open(init_py_path, 'w', encoding='utf-8') as file:
|
|
44
|
+
file.write(self.initpy)
|
|
45
|
+
self.initpy = None
|
|
46
|
+
else:
|
|
47
|
+
with open(init_py_path, 'r', encoding='utf-8') as file:
|
|
48
|
+
self.initpy = file.read()
|
|
49
|
+
os.remove(init_py_path)
|
module/single_py2pyd.py
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
'''
|
|
2
|
+
Author: gu lei
|
|
3
|
+
Date: 2023-01-20 13:52:06
|
|
4
|
+
LastEditTime: 2023-09-26 10:43:03
|
|
5
|
+
LastEditors: gu lei
|
|
6
|
+
'''
|
|
7
|
+
import os
|
|
8
|
+
import shutil
|
|
9
|
+
import glob
|
|
10
|
+
import subprocess
|
|
11
|
+
import sys
|
|
12
|
+
from loguru import logger
|
|
13
|
+
|
|
14
|
+
def py2pyd(path):
|
|
15
|
+
"""
|
|
16
|
+
将单个Python文件转换为pyd/so文件
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
path: Python文件路径
|
|
20
|
+
"""
|
|
21
|
+
logger.info(f"==========================================")
|
|
22
|
+
logger.info(f"开始处理文件: {path}")
|
|
23
|
+
logger.info(f"当前工作目录: {os.getcwd()}")
|
|
24
|
+
|
|
25
|
+
# 保存原始工作目录
|
|
26
|
+
original_dir = os.getcwd()
|
|
27
|
+
try:
|
|
28
|
+
# 检查Cython是否已安装
|
|
29
|
+
try:
|
|
30
|
+
import Cython
|
|
31
|
+
except ImportError:
|
|
32
|
+
logger.error("缺少必要的依赖: Cython")
|
|
33
|
+
logger.info("请先安装依赖: pip install cython")
|
|
34
|
+
return False
|
|
35
|
+
|
|
36
|
+
# 转换为绝对路径
|
|
37
|
+
abs_path = os.path.abspath(path)
|
|
38
|
+
folder_path = os.path.dirname(abs_path) # 文件夹路径
|
|
39
|
+
file_path: str = os.path.basename(abs_path) # 带py的文件名
|
|
40
|
+
filename = file_path.split('.py')[0] # 不带py的文件名
|
|
41
|
+
|
|
42
|
+
logger.info(f"目标文件夹路径: {folder_path}")
|
|
43
|
+
logger.info(f"文件名: {file_path}")
|
|
44
|
+
|
|
45
|
+
# 更改工作目录
|
|
46
|
+
os.chdir(folder_path)
|
|
47
|
+
logger.info(f"切换后的工作目录: {os.getcwd()}")
|
|
48
|
+
|
|
49
|
+
# 根据系统配置编译参数和链接参数
|
|
50
|
+
extra_compile_args = []
|
|
51
|
+
extra_link_args = []
|
|
52
|
+
|
|
53
|
+
if sys.platform == 'darwin': # macOS
|
|
54
|
+
extra_compile_args = ['-Wno-unreachable-code']
|
|
55
|
+
# 对于Conda环境,修复重复rpath警告
|
|
56
|
+
if 'conda' in sys.prefix or 'miniconda' in sys.prefix:
|
|
57
|
+
extra_link_args = ['-Wl,-rpath,@loader_path/../lib']
|
|
58
|
+
elif sys.platform.startswith('linux'): # Linux
|
|
59
|
+
extra_compile_args = ['-Wno-unreachable-code']
|
|
60
|
+
# 对于Conda环境,修复重复rpath警告
|
|
61
|
+
if 'conda' in sys.prefix or 'miniconda' in sys.prefix:
|
|
62
|
+
extra_link_args = ['-Wl,-rpath,$ORIGIN/../lib']
|
|
63
|
+
# Windows不需要这些参数
|
|
64
|
+
|
|
65
|
+
# 生成setup.py文件
|
|
66
|
+
with open('setup.py', 'w') as f:
|
|
67
|
+
f.write('from setuptools import setup, Extension\n')
|
|
68
|
+
f.write('from Cython.Build import cythonize\n')
|
|
69
|
+
f.write('import sys\n\n')
|
|
70
|
+
|
|
71
|
+
# 写入编译选项
|
|
72
|
+
f.write('# 配置编译参数\n')
|
|
73
|
+
f.write('extra_compile_args = %s\n' % extra_compile_args)
|
|
74
|
+
f.write('extra_link_args = %s\n\n' % extra_link_args)
|
|
75
|
+
|
|
76
|
+
f.write('# 创建扩展模块\n')
|
|
77
|
+
f.write('extensions = [\n')
|
|
78
|
+
f.write(' Extension(\n')
|
|
79
|
+
f.write(f" '{filename}',\n")
|
|
80
|
+
f.write(f" ['{file_path}'],\n")
|
|
81
|
+
f.write(' extra_compile_args=extra_compile_args,\n')
|
|
82
|
+
f.write(' extra_link_args=extra_link_args\n')
|
|
83
|
+
f.write(' )\n')
|
|
84
|
+
f.write(']\n\n')
|
|
85
|
+
|
|
86
|
+
f.write('setup(\n')
|
|
87
|
+
f.write(f" name='{filename}',\n")
|
|
88
|
+
f.write(' ext_modules=cythonize(\n')
|
|
89
|
+
f.write(' extensions,\n')
|
|
90
|
+
f.write(" compiler_directives={'language_level': '3'}\n")
|
|
91
|
+
f.write(' )\n')
|
|
92
|
+
f.write(')\n')
|
|
93
|
+
|
|
94
|
+
logger.info(f"开始执行 setup.py")
|
|
95
|
+
try:
|
|
96
|
+
subprocess.check_call(['python', 'setup.py', 'build_ext', '--inplace'])
|
|
97
|
+
except subprocess.CalledProcessError as e:
|
|
98
|
+
logger.error(f"执行setup.py失败: {e}")
|
|
99
|
+
logger.error("请确保已正确安装Cython,并且Python环境中有适当的编译器")
|
|
100
|
+
# 清理临时文件
|
|
101
|
+
if os.path.exists('setup.py'):
|
|
102
|
+
os.remove('setup.py')
|
|
103
|
+
return False
|
|
104
|
+
|
|
105
|
+
# 确定扩展名 (.so 或 .pyd)
|
|
106
|
+
is_windows = sys.platform.startswith('win')
|
|
107
|
+
extension = '.pyd' if is_windows else '.so'
|
|
108
|
+
output_file = f"{filename}{extension}"
|
|
109
|
+
logger.info(f"目标文件名: {output_file}")
|
|
110
|
+
|
|
111
|
+
if os.path.exists(output_file):
|
|
112
|
+
logger.info(f"删除已存在的文件: {output_file}")
|
|
113
|
+
os.remove(output_file) # 删除老的文件
|
|
114
|
+
|
|
115
|
+
# 查找生成的扩展文件
|
|
116
|
+
if is_windows:
|
|
117
|
+
ext_files = glob.glob(filename + "*.pyd")
|
|
118
|
+
else:
|
|
119
|
+
ext_files = glob.glob(filename + "*.so")
|
|
120
|
+
|
|
121
|
+
if not ext_files:
|
|
122
|
+
logger.error(f"未找到编译后的文件")
|
|
123
|
+
return False
|
|
124
|
+
|
|
125
|
+
logger.info(f"找到的文件: {ext_files}")
|
|
126
|
+
|
|
127
|
+
os.rename(ext_files[0], output_file) # 改名字,删除多余的cp38-win_amd64.等
|
|
128
|
+
logger.info(f"重命名文件完成")
|
|
129
|
+
|
|
130
|
+
# 清理临时文件
|
|
131
|
+
logger.info("开始清理临时文件")
|
|
132
|
+
if os.path.exists('%s.c' % filename):
|
|
133
|
+
os.remove('%s.c' % filename) # 删除临时文件
|
|
134
|
+
if os.path.exists('build'):
|
|
135
|
+
shutil.rmtree('build')
|
|
136
|
+
if os.path.exists('setup.py'):
|
|
137
|
+
os.remove('setup.py') # 删除掉生成的setup.py
|
|
138
|
+
if os.path.exists('__pycache__'):
|
|
139
|
+
shutil.rmtree('__pycache__') # 删除 __pycache__文件夹
|
|
140
|
+
[os.remove(i) for i in glob.glob("*.ui")] # 删除ui文件
|
|
141
|
+
logger.info("清理临时文件完成")
|
|
142
|
+
logger.info(f"==========================================\n")
|
|
143
|
+
return True
|
|
144
|
+
|
|
145
|
+
except Exception as e:
|
|
146
|
+
logger.error(f"处理文件时发生错误: {e}")
|
|
147
|
+
return False
|
|
148
|
+
finally:
|
|
149
|
+
# 恢复原始工作目录
|
|
150
|
+
os.chdir(original_dir)
|
|
151
|
+
logger.info(f"恢复原始工作目录: {original_dir}")
|
|
152
|
+
logger.info(f"==========================================\n")
|
|
153
|
+
|
|
154
|
+
if __name__ == "__main__":
|
|
155
|
+
import argparse
|
|
156
|
+
|
|
157
|
+
parser = argparse.ArgumentParser(description="将单个Python文件转换为pyd/so文件")
|
|
158
|
+
parser.add_argument("file_path", help="要转换的Python文件路径")
|
|
159
|
+
|
|
160
|
+
args = parser.parse_args()
|
|
161
|
+
py2pyd(args.file_path)
|
py2pyd.py
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
'''
|
|
4
|
+
Author: gu lei
|
|
5
|
+
Date: 2023-01-20 13:52:06
|
|
6
|
+
LastEditTime: 2023-09-26 10:43:03
|
|
7
|
+
LastEditors: gu lei
|
|
8
|
+
'''
|
|
9
|
+
import os
|
|
10
|
+
import sys
|
|
11
|
+
import argparse
|
|
12
|
+
from loguru import logger
|
|
13
|
+
|
|
14
|
+
def check_dependencies():
|
|
15
|
+
"""检查必要的依赖是否已安装"""
|
|
16
|
+
try:
|
|
17
|
+
import Cython
|
|
18
|
+
logger.info(f"检测到Cython版本: {Cython.__version__}")
|
|
19
|
+
return True
|
|
20
|
+
except ImportError:
|
|
21
|
+
logger.error("缺少必要的依赖: Cython \t 请先安装依赖: pip install cython")
|
|
22
|
+
return False
|
|
23
|
+
|
|
24
|
+
from module.single_py2pyd import py2pyd
|
|
25
|
+
from module.fileConversion import FileConversion
|
|
26
|
+
|
|
27
|
+
def main():
|
|
28
|
+
# 检查依赖
|
|
29
|
+
if not check_dependencies():
|
|
30
|
+
sys.exit(1)
|
|
31
|
+
|
|
32
|
+
parser = argparse.ArgumentParser(description="将Python文件转换为pyd/so文件")
|
|
33
|
+
parser.add_argument("path", help="要转换的Python文件或目录路径")
|
|
34
|
+
parser.add_argument("-r", "--recursive", action="store_true", help="递归处理目录")
|
|
35
|
+
parser.add_argument("--remove", action="store_true", help="转换后删除原始.py文件")
|
|
36
|
+
|
|
37
|
+
args = parser.parse_args()
|
|
38
|
+
|
|
39
|
+
path = args.path
|
|
40
|
+
|
|
41
|
+
if not os.path.exists(path):
|
|
42
|
+
logger.error(f"路径不存在: {path}")
|
|
43
|
+
sys.exit(1)
|
|
44
|
+
|
|
45
|
+
success = False
|
|
46
|
+
|
|
47
|
+
if os.path.isfile(path):
|
|
48
|
+
# 处理单个文件
|
|
49
|
+
if not path.endswith(".py"):
|
|
50
|
+
logger.error(f"不是Python文件: {path}")
|
|
51
|
+
sys.exit(1)
|
|
52
|
+
logger.info(f"处理单个文件: {path}")
|
|
53
|
+
success = py2pyd(path)
|
|
54
|
+
if success and args.remove:
|
|
55
|
+
logger.info(f"删除原始文件: {path}")
|
|
56
|
+
os.remove(path)
|
|
57
|
+
elif os.path.isdir(path):
|
|
58
|
+
# 处理目录
|
|
59
|
+
if args.recursive:
|
|
60
|
+
logger.info(f"递归处理目录: {path}")
|
|
61
|
+
converter = FileConversion()
|
|
62
|
+
success = converter.get_all_file(path, args.remove)
|
|
63
|
+
else:
|
|
64
|
+
# 仅处理当前目录下的.py文件
|
|
65
|
+
logger.info(f"处理目录: {path}")
|
|
66
|
+
success_count = 0
|
|
67
|
+
fail_count = 0
|
|
68
|
+
for filename in os.listdir(path):
|
|
69
|
+
if filename.endswith(".py"):
|
|
70
|
+
file_path = os.path.join(path, filename)
|
|
71
|
+
file_success = py2pyd(file_path)
|
|
72
|
+
if file_success:
|
|
73
|
+
success_count += 1
|
|
74
|
+
if args.remove:
|
|
75
|
+
logger.info(f"删除原始文件: {file_path}")
|
|
76
|
+
os.remove(file_path)
|
|
77
|
+
else:
|
|
78
|
+
fail_count += 1
|
|
79
|
+
|
|
80
|
+
logger.info(f"处理完成!成功: {success_count} 个文件,失败: {fail_count} 个文件")
|
|
81
|
+
success = success_count > 0 and fail_count == 0
|
|
82
|
+
|
|
83
|
+
if success:
|
|
84
|
+
logger.info("处理完成!全部转换成功!")
|
|
85
|
+
sys.exit(0)
|
|
86
|
+
else:
|
|
87
|
+
logger.error("处理完成,但有部分文件转换失败!")
|
|
88
|
+
sys.exit(1)
|
|
89
|
+
|
|
90
|
+
if __name__ == "__main__":
|
|
91
|
+
main()
|