tretool 0.2.1__py3-none-any.whl → 1.0.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.
- tretool/__init__.py +39 -12
- tretool/config.py +406 -170
- tretool/decoratorlib.py +423 -0
- tretool/encoding.py +404 -75
- tretool/httplib.py +730 -0
- tretool/jsonlib.py +619 -151
- tretool/logger.py +712 -0
- tretool/mathlib.py +0 -33
- tretool/path.py +19 -0
- tretool/platformlib.py +469 -314
- tretool/plugin.py +437 -237
- tretool/smartCache.py +569 -0
- tretool/tasklib.py +730 -0
- tretool/transform/docx.py +544 -0
- tretool/transform/pdf.py +273 -95
- tretool/ziplib.py +664 -0
- {tretool-0.2.1.dist-info → tretool-1.0.0.dist-info}/METADATA +11 -5
- tretool-1.0.0.dist-info/RECORD +24 -0
- tretool/markfunc.py +0 -152
- tretool/memorizeTools.py +0 -24
- tretool/writeLog.py +0 -69
- tretool-0.2.1.dist-info/RECORD +0 -20
- {tretool-0.2.1.dist-info → tretool-1.0.0.dist-info}/WHEEL +0 -0
- {tretool-0.2.1.dist-info → tretool-1.0.0.dist-info}/licenses/LICENSE +0 -0
- {tretool-0.2.1.dist-info → tretool-1.0.0.dist-info}/top_level.txt +0 -0
tretool/platformlib.py
CHANGED
@@ -2,331 +2,486 @@ import os
|
|
2
2
|
import sys
|
3
3
|
import ctypes
|
4
4
|
import platform
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
5
|
+
import time
|
6
|
+
import warnings
|
7
|
+
import threading
|
8
|
+
import subprocess
|
9
|
+
import re
|
10
|
+
import json
|
11
|
+
from typing import (Any, Dict, List, Union, SupportsIndex, Optional, Tuple)
|
12
|
+
from enum import Enum, auto
|
13
|
+
from dataclasses import dataclass
|
14
|
+
from pathlib import Path
|
15
|
+
from collections import defaultdict
|
16
|
+
|
17
|
+
class PlatformType(Enum):
|
18
|
+
"""平台类型枚举"""
|
19
|
+
WINDOWS = auto()
|
20
|
+
LINUX = auto()
|
21
|
+
MACOS = auto()
|
22
|
+
UNIX = auto() # 其他UNIX系统
|
23
|
+
JAVA = auto() # Jython环境
|
24
|
+
UNKNOWN = auto()
|
25
|
+
|
26
|
+
class PythonImplementation(Enum):
|
27
|
+
"""Python实现枚举"""
|
28
|
+
CPYTHON = auto()
|
29
|
+
PYPY = auto()
|
30
|
+
IRONPYTHON = auto()
|
31
|
+
JYTHON = auto()
|
32
|
+
UNKNOWN = auto()
|
33
|
+
|
34
|
+
class ByteOrder(Enum):
|
35
|
+
"""字节序枚举"""
|
36
|
+
LITTLE_ENDIAN = auto()
|
37
|
+
BIG_ENDIAN = auto()
|
38
|
+
UNKNOWN = auto()
|
39
|
+
|
40
|
+
@dataclass(frozen=True)
|
41
|
+
class SystemInfo:
|
42
|
+
"""系统信息数据类"""
|
43
|
+
system: str
|
44
|
+
release: str
|
45
|
+
version: str
|
46
|
+
machine: str
|
47
|
+
processor: str
|
48
|
+
platform_type: PlatformType
|
49
|
+
byte_order: ByteOrder
|
50
|
+
|
51
|
+
@dataclass(frozen=True)
|
52
|
+
class PythonBuildInfo:
|
53
|
+
"""Python构建信息数据类"""
|
54
|
+
version: str
|
55
|
+
version_tuple: Tuple[int, int, int]
|
56
|
+
build_number: str
|
57
|
+
build_date: str
|
58
|
+
compiler: str
|
59
|
+
build_options: Dict[str, bool]
|
60
|
+
is_debug: bool
|
61
|
+
is_wide_unicode: bool
|
62
|
+
git_info: Optional[Tuple[str, str]] = None # (commit_hash, branch)
|
63
|
+
|
64
|
+
@dataclass(frozen=True)
|
65
|
+
class PythonRuntimeInfo:
|
66
|
+
"""Python运行时信息数据类"""
|
67
|
+
executable: str
|
68
|
+
path: str
|
69
|
+
flags: Dict[str, Any]
|
70
|
+
byte_order: ByteOrder
|
71
|
+
max_unicode: int
|
72
|
+
implementation: PythonImplementation
|
73
|
+
dll_path: Optional[str] = None
|
74
|
+
prefix: Optional[str] = None
|
75
|
+
base_prefix: Optional[str] = None
|
76
|
+
|
77
|
+
@dataclass(frozen=True)
|
78
|
+
class EnvironmentInfo:
|
79
|
+
"""环境信息数据类"""
|
80
|
+
system: SystemInfo
|
81
|
+
python_build: PythonBuildInfo
|
82
|
+
python_runtime: PythonRuntimeInfo
|
83
|
+
environment_vars: Dict[str, str]
|
84
|
+
python_paths: Dict[str, List[str]]
|
85
|
+
installed_packages: Dict[str, str]
|
86
|
+
|
87
|
+
class EnvironmentInspector:
|
49
88
|
"""
|
50
|
-
|
51
|
-
dll = get_python_dll()
|
52
|
-
Py_GetVersion = dll.Py_GetVersion
|
53
|
-
Py_GetVersion.restype = ctypes.c_char_p
|
54
|
-
version_info = Py_GetVersion().decode('ascii')
|
55
|
-
return version_info.split('[')[1].split(']')[0]
|
56
|
-
except Exception as e:
|
57
|
-
return f'Error: {str(e)}'
|
58
|
-
|
59
|
-
|
60
|
-
def get_python_path() -> str:
|
61
|
-
"""
|
62
|
-
获取 Python 安装根目录(如 C:\\Python39)
|
63
|
-
"""
|
64
|
-
try:
|
65
|
-
return sys.executable.rsplit('\\', 1)[0]
|
89
|
+
终极Python环境检测工具
|
66
90
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
91
|
+
特性:
|
92
|
+
- 全面的系统信息检测
|
93
|
+
- 详细的Python构建和运行时信息
|
94
|
+
- 线程安全设计
|
95
|
+
- 类型安全接口
|
96
|
+
- 跨平台支持
|
97
|
+
- 智能缓存机制
|
98
|
+
- 依赖包检测
|
74
99
|
"""
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
100
|
+
|
101
|
+
def __init__(self):
|
102
|
+
self._cache = {}
|
103
|
+
self._lock = threading.RLock()
|
104
|
+
self._package_cache = None
|
105
|
+
self._package_cache_time = 0
|
106
|
+
|
107
|
+
def get_system_info(self, refresh: bool = False) -> SystemInfo:
|
108
|
+
"""
|
109
|
+
获取系统信息
|
110
|
+
|
111
|
+
参数:
|
112
|
+
refresh: 是否强制刷新缓存
|
113
|
+
|
114
|
+
返回:
|
115
|
+
SystemInfo对象
|
116
|
+
"""
|
117
|
+
with self._lock:
|
118
|
+
if not refresh and 'system_info' in self._cache:
|
119
|
+
return self._cache['system_info']
|
120
|
+
|
121
|
+
uname = platform.uname()
|
122
|
+
system = uname.system
|
123
|
+
platform_type = self._determine_platform_type(system)
|
124
|
+
|
125
|
+
info = SystemInfo(
|
126
|
+
system=system,
|
127
|
+
release=uname.release,
|
128
|
+
version=uname.version,
|
129
|
+
machine=uname.machine,
|
130
|
+
processor=uname.processor,
|
131
|
+
platform_type=platform_type,
|
132
|
+
byte_order=self._get_byteorder_enum()
|
133
|
+
)
|
134
|
+
|
135
|
+
self._cache['system_info'] = info
|
136
|
+
return info
|
137
|
+
|
138
|
+
def get_python_build_info(self, refresh: bool = False) -> PythonBuildInfo:
|
139
|
+
"""
|
140
|
+
获取Python构建信息
|
141
|
+
|
142
|
+
参数:
|
143
|
+
refresh: 是否强制刷新缓存
|
144
|
+
|
145
|
+
返回:
|
146
|
+
PythonBuildInfo对象
|
147
|
+
"""
|
148
|
+
with self._lock:
|
149
|
+
if not refresh and 'build_info' in self._cache:
|
150
|
+
return self._cache['build_info']
|
151
|
+
|
152
|
+
version_tuple = (sys.version_info.major, sys.version_info.minor, sys.version_info.micro)
|
153
|
+
version = f"{version_tuple[0]}.{version_tuple[1]}.{version_tuple[2]}"
|
154
|
+
build_str = sys.version
|
155
|
+
build_parts = re.search(r'\((.+?)\)', build_str)
|
156
|
+
build_info = build_parts.group(1) if build_parts else "unknown"
|
157
|
+
|
158
|
+
# 解析构建日期和编译器
|
159
|
+
build_date, compiler = self._parse_build_info(build_info)
|
160
|
+
|
161
|
+
info = PythonBuildInfo(
|
162
|
+
version=version,
|
163
|
+
version_tuple=version_tuple,
|
164
|
+
build_number=self._get_build_number(),
|
165
|
+
build_date=build_date,
|
166
|
+
compiler=compiler,
|
167
|
+
build_options=self._parse_build_options(),
|
168
|
+
is_debug=self._is_debug_build(),
|
169
|
+
is_wide_unicode=sys.maxunicode > 0xFFFF,
|
170
|
+
git_info=self._get_git_info()
|
171
|
+
)
|
172
|
+
|
173
|
+
self._cache['build_info'] = info
|
174
|
+
return info
|
175
|
+
|
176
|
+
def get_python_runtime_info(self, refresh: bool = False) -> PythonRuntimeInfo:
|
177
|
+
"""
|
178
|
+
获取Python运行时信息
|
179
|
+
|
180
|
+
参数:
|
181
|
+
refresh: 是否强制刷新缓存
|
182
|
+
|
183
|
+
返回:
|
184
|
+
PythonRuntimeInfo对象
|
185
|
+
"""
|
186
|
+
with self._lock:
|
187
|
+
if not refresh and 'runtime_info' in self._cache:
|
188
|
+
return self._cache['runtime_info']
|
189
|
+
|
190
|
+
impl = self._get_implementation()
|
191
|
+
dll_path = self._get_python_dll_path() if impl == PythonImplementation.CPYTHON else None
|
192
|
+
|
193
|
+
info = PythonRuntimeInfo(
|
194
|
+
executable=sys.executable,
|
195
|
+
path=os.path.dirname(sys.executable),
|
196
|
+
flags=self._get_runtime_flags(),
|
197
|
+
byte_order=self._get_byteorder_enum(),
|
198
|
+
max_unicode=sys.maxunicode,
|
199
|
+
implementation=impl,
|
200
|
+
dll_path=dll_path,
|
201
|
+
prefix=sys.prefix,
|
202
|
+
base_prefix=getattr(sys, 'base_prefix', sys.prefix)
|
203
|
+
)
|
204
|
+
|
205
|
+
self._cache['runtime_info'] = info
|
206
|
+
return info
|
207
|
+
|
208
|
+
def get_installed_packages(self, refresh: bool = False) -> Dict[str, str]:
|
209
|
+
"""
|
210
|
+
获取已安装的Python包列表
|
211
|
+
|
212
|
+
参数:
|
213
|
+
refresh: 是否强制刷新缓存
|
214
|
+
|
215
|
+
返回:
|
216
|
+
包名到版本的字典
|
217
|
+
"""
|
218
|
+
with self._lock:
|
219
|
+
current_time = time.time()
|
220
|
+
if not refresh and self._package_cache and current_time - self._package_cache_time < 300: # 5分钟缓存
|
221
|
+
return self._package_cache.copy()
|
222
|
+
|
223
|
+
try:
|
224
|
+
# 使用pip list命令获取包列表
|
225
|
+
result = subprocess.run(
|
226
|
+
[sys.executable, '-m', 'pip', 'list', '--format=json'],
|
227
|
+
capture_output=True,
|
228
|
+
text=True,
|
229
|
+
check=True
|
230
|
+
)
|
231
|
+
packages = json.loads(result.stdout)
|
232
|
+
package_dict = {pkg['name']: pkg['version'] for pkg in packages}
|
233
|
+
|
234
|
+
self._package_cache = package_dict
|
235
|
+
self._package_cache_time = current_time
|
236
|
+
return package_dict
|
237
|
+
except Exception as e:
|
238
|
+
warnings.warn(f"获取安装包列表失败: {str(e)}")
|
239
|
+
return {}
|
240
|
+
|
241
|
+
def get_environment_info(self) -> EnvironmentInfo:
|
242
|
+
"""
|
243
|
+
获取完整环境信息
|
244
|
+
|
245
|
+
返回:
|
246
|
+
EnvironmentInfo对象
|
247
|
+
"""
|
248
|
+
with self._lock:
|
249
|
+
return EnvironmentInfo(
|
250
|
+
system=self.get_system_info(),
|
251
|
+
python_build=self.get_python_build_info(),
|
252
|
+
python_runtime=self.get_python_runtime_info(),
|
253
|
+
environment_vars=self._get_environment_vars(),
|
254
|
+
python_paths=self._get_python_paths(),
|
255
|
+
installed_packages=self.get_installed_packages()
|
256
|
+
)
|
257
|
+
|
258
|
+
def _get_byteorder_enum(self) -> ByteOrder:
|
259
|
+
"""获取字节顺序枚举"""
|
260
|
+
byteorder = sys.byteorder
|
261
|
+
if byteorder == 'little':
|
262
|
+
return ByteOrder.LITTLE_ENDIAN
|
263
|
+
elif byteorder == 'big':
|
264
|
+
return ByteOrder.BIG_ENDIAN
|
265
|
+
else:
|
266
|
+
return ByteOrder.UNKNOWN
|
267
|
+
|
268
|
+
def _determine_platform_type(self, system: str) -> PlatformType:
|
269
|
+
"""确定平台类型"""
|
270
|
+
system_lower = system.lower()
|
271
|
+
if 'linux' in system_lower:
|
272
|
+
return PlatformType.LINUX
|
273
|
+
elif 'windows' in system_lower:
|
274
|
+
return PlatformType.WINDOWS
|
275
|
+
elif 'darwin' in system_lower or 'macos' in system_lower:
|
276
|
+
return PlatformType.MACOS
|
277
|
+
elif 'java' in system_lower:
|
278
|
+
return PlatformType.JAVA
|
279
|
+
elif any(unix in system_lower for unix in ['bsd', 'solaris', 'aix']):
|
280
|
+
return PlatformType.UNIX
|
281
|
+
else:
|
282
|
+
return PlatformType.UNKNOWN
|
283
|
+
|
284
|
+
def _get_build_number(self) -> str:
|
285
|
+
"""获取构建号"""
|
286
|
+
if hasattr(sys, 'version_info') and hasattr(sys.version_info, 'build'):
|
287
|
+
return str(sys.version_info.build[0])
|
173
288
|
return "unknown"
|
174
|
-
|
175
|
-
|
176
|
-
def get_byteorder() -> str:
|
177
|
-
"""
|
178
|
-
智能检测字节顺序(优先使用标准库)
|
179
|
-
"""
|
180
|
-
try:
|
181
|
-
import sys
|
182
|
-
return sys.byteorder
|
183
|
-
except ImportError:
|
184
|
-
try:
|
185
|
-
import ctypes
|
186
|
-
num = 0x12345678
|
187
|
-
buf = (ctypes.c_byte * 4).from_buffer_copy(ctypes.c_uint32(num))
|
188
|
-
return 'big' if buf[0] == 0x12 else 'little'
|
189
|
-
except:
|
190
|
-
return 'unknown'
|
191
|
-
|
192
|
-
|
193
|
-
def get_args(index: SupportsIndex = None) -> Union[List[str], str]:
|
194
|
-
"""
|
195
|
-
获取命令行参数(支持索引访问)
|
196
289
|
|
197
|
-
|
198
|
-
|
290
|
+
def _parse_build_info(self, build_str: str) -> Tuple[str, str]:
|
291
|
+
"""解析构建信息字符串"""
|
292
|
+
# 尝试解析日期和编译器
|
293
|
+
date_match = re.search(r'(\w{3} \d{1,2} \d{4},? \d{2}:\d{2}:\d{2})', build_str)
|
294
|
+
date = date_match.group(0) if date_match else "unknown"
|
199
295
|
|
200
|
-
|
201
|
-
|
202
|
-
当指定index时:返回对应位置的参数值
|
296
|
+
compiler_match = re.search(r'\[(.*?)\]', build_str)
|
297
|
+
compiler = compiler_match.group(1) if compiler_match else "unknown"
|
203
298
|
|
204
|
-
|
205
|
-
IndexError - 当索引超出范围时引发
|
206
|
-
"""
|
207
|
-
args = sys.argv
|
299
|
+
return date, compiler
|
208
300
|
|
209
|
-
|
210
|
-
|
301
|
+
def _parse_build_options(self) -> Dict[str, bool]:
|
302
|
+
"""解析构建选项"""
|
303
|
+
build_str = sys.version
|
304
|
+
options = {}
|
305
|
+
|
306
|
+
# 常见构建选项检测
|
307
|
+
common_options = [
|
308
|
+
'WITH_PYMALLOC', 'WITH_THREAD', 'PYTHONFRAMEWORK',
|
309
|
+
'WITH_DOC_STRINGS', 'WITH_VALGRIND', 'WITH_PYDEBUG'
|
310
|
+
]
|
311
|
+
|
312
|
+
for opt in common_options:
|
313
|
+
options[opt] = opt in build_str
|
314
|
+
|
315
|
+
# 特殊选项检测
|
316
|
+
options['PYMALLOC'] = 'pymalloc' in build_str.lower()
|
317
|
+
options['DEBUG'] = 'debug' in build_str.lower()
|
318
|
+
|
319
|
+
return options
|
211
320
|
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
321
|
+
def _get_git_info(self) -> Optional[Tuple[str, str]]:
|
322
|
+
"""获取Git版本信息"""
|
323
|
+
try:
|
324
|
+
# 检查是否有git信息
|
325
|
+
if not hasattr(sys, '_git'):
|
326
|
+
return None
|
327
|
+
|
328
|
+
git_info = sys._git
|
329
|
+
return (git_info[0], git_info[1]) if git_info else None
|
330
|
+
except Exception:
|
331
|
+
return None
|
221
332
|
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
- 'build_info': 构建配置信息
|
226
|
-
- 'unicode_info': Unicode相关配置
|
333
|
+
def _is_debug_build(self) -> bool:
|
334
|
+
"""检查是否是调试版本"""
|
335
|
+
return hasattr(sys, 'gettotalrefcount')
|
227
336
|
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
hash_randomization: 哈希随机化
|
242
|
-
isolated: 隔离模式
|
243
|
-
dev_mode: 开发模式
|
244
|
-
utf8_mode: UTF-8模式
|
245
|
-
warn_default_encoding: 默认编码警告
|
246
|
-
safe_path: 安全路径模式
|
247
|
-
int_max_str_digits: 整数字符串转换最大位数
|
248
|
-
"""
|
249
|
-
return {
|
250
|
-
'runtime_flags': get_runtime_flags(),
|
251
|
-
'build_info': get_build_info(),
|
252
|
-
'unicode_info': get_unicode_info()
|
253
|
-
}
|
254
|
-
|
255
|
-
|
256
|
-
def get_runtime_flags() -> Dict[str, Any]:
|
257
|
-
"""获取sys.flags中的所有运行时标志"""
|
258
|
-
flags = sys.flags
|
259
|
-
return {
|
260
|
-
'debug': flags.debug,
|
261
|
-
'inspect': flags.inspect,
|
262
|
-
'interactive': flags.interactive,
|
263
|
-
'optimize': flags.optimize,
|
264
|
-
'dont_write_bytecode': flags.dont_write_bytecode,
|
265
|
-
'no_user_site': flags.no_user_site,
|
266
|
-
'no_site': flags.no_site,
|
267
|
-
'ignore_environment': flags.ignore_environment,
|
268
|
-
'verbose': flags.verbose,
|
269
|
-
'bytes_warning': flags.bytes_warning,
|
270
|
-
'quiet': flags.quiet,
|
271
|
-
'hash_randomization': flags.hash_randomization,
|
272
|
-
'isolated': flags.isolated,
|
273
|
-
'dev_mode': flags.dev_mode,
|
274
|
-
'utf8_mode': flags.utf8_mode,
|
275
|
-
'warn_default_encoding': getattr(flags, 'warn_default_encoding', 0),
|
276
|
-
'safe_path': getattr(flags, 'safe_path', False),
|
277
|
-
'int_max_str_digits': getattr(flags, 'int_max_str_digits', 0)
|
278
|
-
}
|
279
|
-
|
280
|
-
|
281
|
-
def get_build_info() -> Dict[str, Any]:
|
282
|
-
"""获取构建配置信息"""
|
283
|
-
return {
|
284
|
-
'debug_build': hasattr(sys, 'gettotalrefcount'),
|
285
|
-
'compiler': get_python_compiler(),
|
286
|
-
'build_options': parse_build_options(),
|
287
|
-
'platform': get_system(),
|
288
|
-
'implementation': get_python_implementation()
|
289
|
-
}
|
290
|
-
|
291
|
-
|
292
|
-
def parse_build_options() -> Dict[str, bool]:
|
293
|
-
"""从构建字符串解析编译选项"""
|
294
|
-
build_str = sys.version
|
295
|
-
options = {}
|
337
|
+
def _get_implementation(self) -> PythonImplementation:
|
338
|
+
"""获取Python实现类型"""
|
339
|
+
impl = sys.implementation.name.lower()
|
340
|
+
if impl == 'cpython':
|
341
|
+
return PythonImplementation.CPYTHON
|
342
|
+
elif impl == 'pypy':
|
343
|
+
return PythonImplementation.PYPY
|
344
|
+
elif impl == 'ironpython':
|
345
|
+
return PythonImplementation.IRONPYTHON
|
346
|
+
elif impl == 'jython':
|
347
|
+
return PythonImplementation.JYTHON
|
348
|
+
else:
|
349
|
+
return PythonImplementation.UNKNOWN
|
296
350
|
|
297
|
-
|
298
|
-
|
299
|
-
|
351
|
+
def _get_runtime_flags(self) -> Dict[str, Any]:
|
352
|
+
"""获取运行时标志"""
|
353
|
+
flags = sys.flags
|
354
|
+
return {
|
355
|
+
'debug': flags.debug,
|
356
|
+
'inspect': flags.inspect,
|
357
|
+
'interactive': flags.interactive,
|
358
|
+
'optimize': flags.optimize,
|
359
|
+
'dont_write_bytecode': flags.dont_write_bytecode,
|
360
|
+
'no_user_site': flags.no_user_site,
|
361
|
+
'no_site': flags.no_site,
|
362
|
+
'ignore_environment': flags.ignore_environment,
|
363
|
+
'verbose': flags.verbose,
|
364
|
+
'bytes_warning': flags.bytes_warning,
|
365
|
+
'quiet': flags.quiet,
|
366
|
+
'hash_randomization': flags.hash_randomization,
|
367
|
+
'isolated': flags.isolated,
|
368
|
+
'dev_mode': flags.dev_mode,
|
369
|
+
'utf8_mode': flags.utf8_mode,
|
370
|
+
'warn_default_encoding': getattr(flags, 'warn_default_encoding', 0),
|
371
|
+
'safe_path': getattr(flags, 'safe_path', False),
|
372
|
+
'int_max_str_digits': getattr(flags, 'int_max_str_digits', 0)
|
373
|
+
}
|
300
374
|
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
375
|
+
def _get_python_dll_path(self) -> Optional[str]:
|
376
|
+
"""获取Python DLL路径"""
|
377
|
+
if platform.system() != 'Windows':
|
378
|
+
return None
|
379
|
+
|
380
|
+
try:
|
381
|
+
# Windows上获取Python DLL路径
|
382
|
+
is_64bit = ctypes.sizeof(ctypes.c_void_p) == 8
|
383
|
+
is_debug = hasattr(sys, 'gettotalrefcount')
|
384
|
+
|
385
|
+
versions = [
|
386
|
+
f"{sys.version_info.major}{sys.version_info.minor}",
|
387
|
+
f"{sys.version_info.major}.{sys.version_info.minor}"
|
388
|
+
]
|
389
|
+
|
390
|
+
suffixes = ['', '_d'] if is_debug else ['']
|
391
|
+
|
392
|
+
for version in versions:
|
393
|
+
for suffix in suffixes:
|
394
|
+
dll_name = f"python{version}{suffix}.dll"
|
395
|
+
try:
|
396
|
+
dll = ctypes.PyDLL(dll_name)
|
397
|
+
return os.path.abspath(dll._name)
|
398
|
+
except OSError:
|
399
|
+
continue
|
400
|
+
|
401
|
+
return None
|
402
|
+
except Exception:
|
403
|
+
return None
|
404
|
+
|
405
|
+
def _get_environment_vars(self) -> Dict[str, str]:
|
406
|
+
"""获取相关环境变量"""
|
407
|
+
relevant_vars = [
|
408
|
+
'PATH', 'PYTHONPATH', 'PYTHONHOME',
|
409
|
+
'VIRTUAL_ENV', 'CONDA_PREFIX',
|
410
|
+
'LANG', 'LC_ALL', 'LC_CTYPE',
|
411
|
+
'PYTHONSTARTUP', 'PYTHONDEBUG',
|
412
|
+
'PYTHONINSPECT', 'PYTHONUNBUFFERED'
|
413
|
+
]
|
414
|
+
return {var: os.getenv(var, '') for var in relevant_vars}
|
415
|
+
|
416
|
+
def _get_python_paths(self) -> Dict[str, List[str]]:
|
417
|
+
"""获取Python路径信息"""
|
418
|
+
return {
|
419
|
+
'sys.path': sys.path,
|
420
|
+
'module_search_paths': list(sys.path_importer_cache.keys()),
|
421
|
+
'stdlib_paths': self._get_stdlib_paths()
|
331
422
|
}
|
332
|
-
|
423
|
+
|
424
|
+
def _get_stdlib_paths(self) -> List[str]:
|
425
|
+
"""获取标准库路径"""
|
426
|
+
stdlib_paths = []
|
427
|
+
for path in sys.path:
|
428
|
+
if 'site-packages' not in path and 'dist-packages' not in path:
|
429
|
+
stdlib_paths.append(path)
|
430
|
+
return stdlib_paths
|
431
|
+
|
432
|
+
# 全局实例
|
433
|
+
_inspector = EnvironmentInspector()
|
434
|
+
|
435
|
+
# 便捷函数
|
436
|
+
def get_system_info() -> SystemInfo:
|
437
|
+
"""获取系统信息"""
|
438
|
+
return _inspector.get_system_info()
|
439
|
+
|
440
|
+
def get_python_build_info() -> PythonBuildInfo:
|
441
|
+
"""获取Python构建信息"""
|
442
|
+
return _inspector.get_python_build_info()
|
443
|
+
|
444
|
+
def get_python_runtime_info() -> PythonRuntimeInfo:
|
445
|
+
"""获取Python运行时信息"""
|
446
|
+
return _inspector.get_python_runtime_info()
|
447
|
+
|
448
|
+
def get_installed_packages(refresh: bool = False) -> Dict[str, str]:
|
449
|
+
"""获取已安装的Python包列表"""
|
450
|
+
return _inspector.get_installed_packages(refresh)
|
451
|
+
|
452
|
+
def get_environment_info() -> EnvironmentInfo:
|
453
|
+
"""获取完整环境信息"""
|
454
|
+
return _inspector.get_environment_info()
|
455
|
+
|
456
|
+
def generate_environment_report(format: str = 'dict') -> Union[Dict[str, Any], str]:
|
457
|
+
"""
|
458
|
+
生成环境报告
|
459
|
+
|
460
|
+
参数:
|
461
|
+
format: 输出格式 ('dict', 'json', 'yaml')
|
462
|
+
|
463
|
+
返回:
|
464
|
+
指定格式的报告
|
465
|
+
"""
|
466
|
+
info = get_environment_info()
|
467
|
+
|
468
|
+
def serialize(obj):
|
469
|
+
if isinstance(obj, (SystemInfo, PythonBuildInfo, PythonRuntimeInfo, EnvironmentInfo)):
|
470
|
+
return {k: serialize(v) for k, v in obj.__dict__.items() if not k.startswith('_')}
|
471
|
+
elif isinstance(obj, Enum):
|
472
|
+
return obj.name
|
473
|
+
elif isinstance(obj, tuple):
|
474
|
+
return list(obj)
|
475
|
+
return obj
|
476
|
+
|
477
|
+
report_dict = serialize(info)
|
478
|
+
|
479
|
+
if format == 'dict':
|
480
|
+
return report_dict
|
481
|
+
elif format == 'json':
|
482
|
+
return json.dumps(report_dict, indent=2)
|
483
|
+
elif format == 'yaml':
|
484
|
+
import yaml
|
485
|
+
return yaml.safe_dump(report_dict)
|
486
|
+
else:
|
487
|
+
raise ValueError(f"不支持的格式: {format}")
|