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/platformlib.py CHANGED
@@ -2,331 +2,486 @@ import os
2
2
  import sys
3
3
  import ctypes
4
4
  import platform
5
- from typing import (Any, Dict, List, Union, SupportsIndex)
6
-
7
-
8
- def get_python_dll() -> ctypes.PyDLL:
9
- """内部函数:获取 Python DLL 句柄"""
10
- is_64bit = ctypes.sizeof(ctypes.c_void_p) == 8
11
- dll_suffix = '_d' if hasattr(sys, 'gettotalrefcount') else ''
12
- dll_name = f"python{''.join(map(str, sys.version_info[:2]))}{dll_suffix}.dll"
13
- return ctypes.PyDLL(dll_name)
14
-
15
-
16
- def get_python_version() -> str:
17
- """
18
- 获取 Python 版本号
19
- 返回格式:'major.minor.micro'
20
- """
21
- try:
22
- dll = get_python_dll()
23
- Py_GetVersion = dll.Py_GetVersion
24
- Py_GetVersion.restype = ctypes.c_char_p
25
- return Py_GetVersion().decode('ascii').split()[0]
26
- except Exception as e:
27
- return f'Error: {str(e)}'
28
-
29
-
30
- def get_python_build() -> str:
31
- """
32
- 获取 Python 构建信息
33
- 返回格式:如 "v3.9.7:8d82e9e9b3, Aug 31 2021, 13:28:12"
34
- """
35
- try:
36
- dll = get_python_dll()
37
- Py_GetVersion = dll.Py_GetVersion
38
- Py_GetVersion.restype = ctypes.c_char_p
39
- version_info = Py_GetVersion().decode('ascii')
40
- return f"v{version_info.split('(', 1)[1].split(')')[0]}"
41
- except Exception as e:
42
- return f'Error: {str(e)}'
43
-
44
-
45
- def get_python_compiler() -> str:
46
- """
47
- 获取 Python 编译器信息
48
- 返回格式:如 "[GCC 8.4.0]"
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
- try:
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
- except Exception as e:
68
- return f'Error: {str(e)}'
69
-
70
-
71
- def get_python_executable() -> str:
72
- """
73
- 获取 Python 解释器路径
91
+ 特性:
92
+ - 全面的系统信息检测
93
+ - 详细的Python构建和运行时信息
94
+ - 线程安全设计
95
+ - 类型安全接口
96
+ - 跨平台支持
97
+ - 智能缓存机制
98
+ - 依赖包检测
74
99
  """
75
- try:
76
- return sys.executable
77
- except Exception as e:
78
- return f'Error: {str(e)}'
79
-
80
-
81
- def get_python_flags() -> Dict[str, bool]:
82
- """
83
- 获取 Python 编译标志
84
- 返回字典包含:
85
- - debug: 是否是调试版本
86
- - utf8_mode: 是否启用UTF-8模式
87
- """
88
- try:
89
- flags = {
90
- 'debug': hasattr(sys, 'gettotalrefcount'),
91
- 'utf8_mode': sys.flags.utf8_mode
92
- }
93
- return flags
94
- except Exception as e:
95
- return {'error': str(e)}
96
-
97
-
98
- def get_python_implementation() -> str:
99
- """
100
- 获取更友好的实现名称
101
- """
102
- impl = sys.implementation.name
103
- return {
104
- 'cpython': 'CPython',
105
- 'pypy': 'PyPy',
106
- 'ironpython': 'IronPython',
107
- 'jython': 'Jython'
108
- }.get(impl, impl.capitalize())
109
-
110
-
111
- def get_full_python_info() -> Dict[str, str]:
112
- """
113
- 获取完整的 Python 信息
114
- 返回包含所有信息的字典
115
- """
116
- return {
117
- 'version': get_python_version(),
118
- 'build': get_python_build(),
119
- 'compiler': get_python_compiler(),
120
- 'path': get_python_path(),
121
- 'executable': get_python_executable(),
122
- 'flags': get_python_flags(),
123
- 'implementation': get_python_implementation()
124
- }
125
-
126
-
127
- def uname():
128
- return platform.uname()
129
-
130
-
131
- def get_system() -> str:
132
- """
133
- 获取操作系统类型(增强版)
134
- 返回:
135
- 'Windows'/'Linux'/'Darwin'/'Java' 等友好名称
136
- """
137
- system = platform.uname().system
138
- return {
139
- 'Linux': 'Linux',
140
- 'Darwin': 'macOS',
141
- 'Windows': 'Windows',
142
- 'Java': 'Java'
143
- }.get(system, system)
144
-
145
-
146
- def release() -> str:
147
- """
148
- 获取操作系统版本号(跨平台)
149
- 返回:
150
- Linux: 内核版本 (如 '5.4.0-80-generic')
151
- Windows: 版本号 (如 '10')
152
- macOS: Darwin 版本 (如 '21.1.0')
153
- """
154
- try:
155
- if hasattr(os, 'uname'):
156
- return os.uname().release
157
- return platform.release()
158
- except Exception:
159
- return "unknown"
160
-
161
-
162
- def machine() -> str:
163
- """
164
- 获取系统架构(跨平台)
165
- 返回:
166
- 'x86_64'/'AMD64'/'arm64' 等标准架构名称
167
- """
168
- try:
169
- if hasattr(os, 'uname'):
170
- return os.uname().machine
171
- return platform.machine()
172
- except Exception:
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
- index - 可选参数索引(支持负数索引)
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
- 当index为None时:返回完整参数列表['script.py', 'arg1', ...]
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
- if index is None:
210
- return args.copy() # 返回副本避免外部修改
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
- try:
213
- return args[index] # 自动支持SupportsIndex类型
214
- except IndexError:
215
- raise IndexError(f"参数索引 {index} 超出范围 (参数总数: {len(args)})") from None
216
-
217
-
218
- def get_all_flags() -> Dict[str, Dict[str, Any]]:
219
- """
220
- 获取Python解释器的完整标志信息
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
- - 'runtime_flags': 运行时标志(来自sys.flags)
225
- - 'build_info': 构建配置信息
226
- - 'unicode_info': Unicode相关配置
333
+ def _is_debug_build(self) -> bool:
334
+ """检查是否是调试版本"""
335
+ return hasattr(sys, 'gettotalrefcount')
227
336
 
228
- 标志说明:
229
- runtime_flags:
230
- debug: 调试模式
231
- inspect: 交互模式后进入检查模式
232
- interactive: 交互模式
233
- optimize: 优化级别 (0/1/2)
234
- dont_write_bytecode: 不生成.pyc文件
235
- no_user_site: 忽略用户site-packages
236
- no_site: 忽略所有site-packages
237
- ignore_environment: 忽略环境变量
238
- verbose: 详细输出
239
- bytes_warning: 字节警告
240
- quiet: 安静模式
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
- for opt in ['WITH_PYMALLOC', 'WITH_THREAD', 'PYTHONFRAMEWORK']:
299
- options[opt] = opt in build_str
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
- options['PYMALLOC'] = 'pymalloc' in build_str.lower()
303
- return options
304
-
305
-
306
- def get_unicode_info() -> Dict[str, Any]:
307
- """获取Unicode配置信息"""
308
- return {
309
- 'maxunicode': sys.maxunicode,
310
- 'wide_build': sys.maxunicode > 0xFFFF,
311
- 'default_encoding': sys.getdefaultencoding(),
312
- 'filesystem_encoding': sys.getfilesystemencoding()
313
- }
314
-
315
-
316
- def get_environment_report() -> Dict[str, Dict[str, str]]:
317
- """生成完整的环境报告"""
318
- return {
319
- 'python': {
320
- 'version': get_python_version(),
321
- 'build': get_python_build(),
322
- 'implementation': get_python_implementation(),
323
- 'compiler': get_python_compiler(),
324
- 'path': get_python_path(),
325
- 'executable': get_python_executable()
326
- },
327
- 'runtime': {
328
- 'byteorder': get_byteorder(),
329
- 'flags': get_all_flags(),
330
- 'argv': get_args()
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}")