ErisPulse 2.4.6.dev3__tar.gz → 2.4.6.dev4__tar.gz

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.
Files changed (130) hide show
  1. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/PKG-INFO +1 -1
  2. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/pyproject.toml +1 -1
  3. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/CLI/commands/run.py +31 -9
  4. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/CLI/commands/run.pyi +3 -0
  5. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/adapter.py +26 -18
  6. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/module.py +12 -0
  7. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/loaders/adapter.py +16 -2
  8. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/loaders/module.py +35 -1
  9. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/sdk.py +34 -0
  10. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/sdk.pyi +19 -0
  11. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/.gitignore +0 -0
  12. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/LICENSE +0 -0
  13. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/README.md +0 -0
  14. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/CLI/__init__.py +0 -0
  15. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/CLI/__init__.pyi +0 -0
  16. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/CLI/base.py +0 -0
  17. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/CLI/base.pyi +0 -0
  18. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/CLI/cli.py +0 -0
  19. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/CLI/cli.pyi +0 -0
  20. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/CLI/commands/__init__.py +0 -0
  21. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/CLI/commands/__init__.pyi +0 -0
  22. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/CLI/commands/create.py +0 -0
  23. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/CLI/commands/create.pyi +0 -0
  24. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/CLI/commands/init.py +0 -0
  25. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/CLI/commands/init.pyi +0 -0
  26. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/CLI/commands/install.py +0 -0
  27. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/CLI/commands/install.pyi +0 -0
  28. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/CLI/commands/list.py +0 -0
  29. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/CLI/commands/list.pyi +0 -0
  30. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/CLI/commands/list_remote.py +0 -0
  31. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/CLI/commands/list_remote.pyi +0 -0
  32. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/CLI/commands/self_update.py +0 -0
  33. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/CLI/commands/self_update.pyi +0 -0
  34. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/CLI/commands/uninstall.py +0 -0
  35. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/CLI/commands/uninstall.pyi +0 -0
  36. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/CLI/commands/upgrade.py +0 -0
  37. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/CLI/commands/upgrade.pyi +0 -0
  38. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/CLI/console.py +0 -0
  39. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/CLI/console.pyi +0 -0
  40. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/CLI/registry.py +0 -0
  41. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/CLI/registry.pyi +0 -0
  42. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/CLI/utils/__init__.py +0 -0
  43. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/CLI/utils/__init__.pyi +0 -0
  44. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/CLI/utils/display.py +0 -0
  45. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/CLI/utils/display.pyi +0 -0
  46. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/CLI/utils/package_manager.py +0 -0
  47. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/CLI/utils/package_manager.pyi +0 -0
  48. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/Bases/__init__.py +0 -0
  49. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/Bases/__init__.pyi +0 -0
  50. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/Bases/adapter.py +0 -0
  51. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/Bases/adapter.pyi +0 -0
  52. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/Bases/manager.py +0 -0
  53. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/Bases/manager.pyi +0 -0
  54. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/Bases/module.py +0 -0
  55. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/Bases/module.pyi +0 -0
  56. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/Bases/storage.py +0 -0
  57. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/Bases/storage.pyi +0 -0
  58. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/Event/__init__.py +0 -0
  59. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/Event/__init__.pyi +0 -0
  60. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/Event/base.py +0 -0
  61. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/Event/base.pyi +0 -0
  62. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/Event/command.py +0 -0
  63. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/Event/command.pyi +0 -0
  64. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/Event/message.py +0 -0
  65. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/Event/message.pyi +0 -0
  66. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/Event/message_builder.py +0 -0
  67. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/Event/message_builder.pyi +0 -0
  68. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/Event/meta.py +0 -0
  69. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/Event/meta.pyi +0 -0
  70. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/Event/notice.py +0 -0
  71. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/Event/notice.pyi +0 -0
  72. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/Event/request.py +0 -0
  73. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/Event/request.pyi +0 -0
  74. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/Event/session_type.py +0 -0
  75. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/Event/session_type.pyi +0 -0
  76. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/Event/wrapper.py +0 -0
  77. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/Event/wrapper.pyi +0 -0
  78. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/__init__.py +0 -0
  79. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/__init__.pyi +0 -0
  80. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/adapter.pyi +0 -0
  81. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/config.py +0 -0
  82. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/config.pyi +0 -0
  83. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/constants.py +0 -0
  84. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/constants.pyi +0 -0
  85. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/lifecycle.py +0 -0
  86. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/lifecycle.pyi +0 -0
  87. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/logger.py +0 -0
  88. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/logger.pyi +0 -0
  89. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/module.pyi +0 -0
  90. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/router.py +0 -0
  91. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/router.pyi +0 -0
  92. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/storage.py +0 -0
  93. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/Core/storage.pyi +0 -0
  94. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/__init__.py +0 -0
  95. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/__init__.pyi +0 -0
  96. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/__main__.py +0 -0
  97. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/__main__.pyi +0 -0
  98. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/finders/__init__.py +0 -0
  99. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/finders/__init__.pyi +0 -0
  100. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/finders/adapter.py +0 -0
  101. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/finders/adapter.pyi +0 -0
  102. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/finders/bases/__init__.py +0 -0
  103. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/finders/bases/__init__.pyi +0 -0
  104. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/finders/bases/finder.py +0 -0
  105. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/finders/bases/finder.pyi +0 -0
  106. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/finders/module.py +0 -0
  107. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/finders/module.pyi +0 -0
  108. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/loaders/__init__.py +0 -0
  109. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/loaders/__init__.pyi +0 -0
  110. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/loaders/adapter.pyi +0 -0
  111. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/loaders/bases/__init__.py +0 -0
  112. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/loaders/bases/__init__.pyi +0 -0
  113. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/loaders/bases/loader.py +0 -0
  114. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/loaders/bases/loader.pyi +0 -0
  115. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/loaders/module.pyi +0 -0
  116. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/loaders/strategy.py +0 -0
  117. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/loaders/strategy.pyi +0 -0
  118. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/runtime/__init__.py +0 -0
  119. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/runtime/__init__.pyi +0 -0
  120. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/runtime/context.py +0 -0
  121. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/runtime/context.pyi +0 -0
  122. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/runtime/exceptions.py +0 -0
  123. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/runtime/exceptions.pyi +0 -0
  124. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/runtime/frame_config.py +0 -0
  125. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/runtime/frame_config.pyi +0 -0
  126. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/web_status/4xx.png +0 -0
  127. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/web_status/5xx.png +0 -0
  128. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/web_status/__init__.py +0 -0
  129. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/web_status/__init__.pyi +0 -0
  130. {erispulse-2.4.6.dev3 → erispulse-2.4.6.dev4}/src/ErisPulse/web_status/unknow.png +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ErisPulse
3
- Version: 2.4.6.dev3
3
+ Version: 2.4.6.dev4
4
4
  Summary: ErisPulse 是一个模块化、可扩展的异步 Python SDK 框架,主要用于构建高效、可维护的机器人应用程序。
5
5
  Author-email: ErisDev <erisdev@88.com>
6
6
  Maintainer-email: "艾莉丝·格雷拉特(WSu2059)" <wsu2059@qq.com>
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "ErisPulse"
7
- version = "2.4.6-dev.3"
7
+ version = "2.4.6-dev.4"
8
8
  description = "ErisPulse 是一个模块化、可扩展的异步 Python SDK 框架,主要用于构建高效、可维护的机器人应用程序。"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -116,28 +116,50 @@ class RunCommand(Command):
116
116
  else:
117
117
  self._run_internal(reload_mode)
118
118
 
119
+ _RESTART_EXIT_CODE = 42
120
+
119
121
  def _run_internal(self, reload_mode: bool):
120
122
  """
121
123
  直接运行 SDK(不指定脚本时)
124
+
125
+ 以子进程方式运行 SDK,支持硬重启:当 SDK 进程以特定退出码退出时,
126
+ 自动重新启动新进程,确保资源完全释放。
122
127
  """
123
128
 
124
- async def _run():
125
- from ... import sdk
129
+ if reload_mode:
130
+ async def _run():
131
+ from ... import sdk
126
132
 
127
- if reload_mode:
128
133
  loop = asyncio.get_running_loop()
129
134
  self._setup_watchdog(".", loop)
135
+ await sdk.run(keep_running=True)
130
136
 
131
- await sdk.run(keep_running=True)
137
+ try:
138
+ asyncio.run(_run())
139
+ except KeyboardInterrupt:
140
+ pass
141
+ finally:
142
+ if hasattr(self, "_observer"):
143
+ self._observer.stop()
144
+ self._observer.join()
145
+ return
146
+
147
+ cmd = [sys.executable, "-c",
148
+ "import asyncio; from ErisPulse import sdk; "
149
+ "asyncio.run(sdk.run(keep_running=True))"]
132
150
 
133
151
  try:
134
- asyncio.run(_run())
152
+ while True:
153
+ process = subprocess.Popen(cmd)
154
+ process.wait()
155
+
156
+ if process.returncode == self._RESTART_EXIT_CODE:
157
+ console.print("[info]收到硬重启请求,正在重新启动...[/]")
158
+ time.sleep(0.5)
159
+ continue
160
+ break
135
161
  except KeyboardInterrupt:
136
162
  pass
137
- finally:
138
- if reload_mode and hasattr(self, "_observer"):
139
- self._observer.stop()
140
- self._observer.join()
141
163
 
142
164
  def _run_script(self, script_path: str, reload_mode: bool):
143
165
  script_path_abs = os.path.abspath(script_path)
@@ -53,6 +53,9 @@ class RunCommand(Command):
53
53
  def _run_internal(self: object, reload_mode: bool) -> ...:
54
54
  """
55
55
  直接运行 SDK(不指定脚本时)
56
+
57
+ 以子进程方式运行 SDK,支持硬重启:当 SDK 进程以特定退出码退出时,
58
+ 自动重新启动新进程,确保资源完全释放。
56
59
  """
57
60
  ...
58
61
  def _run_script(self: object, script_path: str, reload_mode: bool) -> ...:
@@ -135,24 +135,32 @@ class AdapterManager(ManagerBase):
135
135
  if existing_instance is not None:
136
136
  self._adapters[platform] = existing_instance
137
137
  else:
138
- # 创建适配器实例
139
- # 检查适配器类 __init__ 方法的参数
140
- init_signature = inspect.signature(adapter_class.__init__)
141
- params = [p for p in init_signature.parameters.values() if p.name != "self"]
142
-
143
- sdk_to_use = self._sdk
144
- if sdk_to_use is None:
145
- from .. import sdk
146
-
147
- sdk_to_use = sdk
148
-
149
- # 根据参数情况创建实例
150
- if params:
151
- instance = adapter_class(sdk_to_use)
152
- else:
153
- instance = adapter_class()
154
-
155
- self._adapters[platform] = instance
138
+ try:
139
+ # 创建适配器实例
140
+ # 检查适配器类 __init__ 方法的参数
141
+ init_signature = inspect.signature(adapter_class.__init__)
142
+ params = [p for p in init_signature.parameters.values() if p.name != "self"]
143
+
144
+ sdk_to_use = self._sdk
145
+ if sdk_to_use is None:
146
+ from .. import sdk
147
+
148
+ sdk_to_use = sdk
149
+
150
+ # 根据参数情况创建实例
151
+ if params:
152
+ instance = adapter_class(sdk_to_use)
153
+ else:
154
+ instance = adapter_class()
155
+
156
+ self._adapters[platform] = instance
157
+ except SystemExit as e:
158
+ logger.error(f"适配器 {platform} 尝试退出进程 (SystemExit({e.code})),已跳过。"
159
+ f"请不要在适配器中使用 sys.exit() 或 raise SystemExit")
160
+ return False
161
+ except Exception as e:
162
+ logger.error(f"创建适配器实例 {platform} 失败: {e}")
163
+ return False
156
164
 
157
165
  return True
158
166
 
@@ -203,6 +203,18 @@ class ModuleManager(ManagerBase):
203
203
  logger.info(f"模块 {module_name} 加载成功")
204
204
  return True
205
205
 
206
+ except SystemExit as e:
207
+ await lifecycle.submit_event(
208
+ "module.load",
209
+ data={
210
+ "module_name": module_name,
211
+ "success": False,
212
+ },
213
+ msg=f"模块 {module_name} 尝试退出进程 (SystemExit)",
214
+ )
215
+ logger.error(f"模块 {module_name} 尝试退出进程 (SystemExit({e.code})),已跳过该模块。"
216
+ f"请不要在模块中使用 sys.exit() 或 raise SystemExit,请改用 raise RuntimeError 或返回错误")
217
+ return False
206
218
  except Exception as e:
207
219
  await lifecycle.submit_event(
208
220
  "module.load",
@@ -91,8 +91,10 @@ class AdapterLoader(BaseLoader):
91
91
 
92
92
  logger.print_section_separator()
93
93
 
94
- except Exception as e:
94
+ except BaseException as e:
95
95
  logger.error(f"加载 {group_name} entry-points 失败: {e}")
96
+ if isinstance(e, SystemExit):
97
+ logger.warning(f"拦截到 SystemExit,已阻止进程退出,跳过后续适配器加载")
96
98
 
97
99
  return objs, enabled_list, disabled_list
98
100
 
@@ -172,6 +174,9 @@ class AdapterLoader(BaseLoader):
172
174
  objs[meta_name] = adapter_obj
173
175
  enabled_list.append(meta_name)
174
176
 
177
+ except SystemExit as e:
178
+ logger.error(f"加载适配器 {meta_name} 时触发 SystemExit({e.code}),已跳过。"
179
+ f"请不要在适配器中使用 sys.exit() 或 raise SystemExit")
175
180
  except Exception as e:
176
181
  logger.error(f"加载适配器 {meta_name} 失败,已跳过: {e}")
177
182
 
@@ -224,6 +229,15 @@ class AdapterLoader(BaseLoader):
224
229
  data={"platform": platform, "success": True},
225
230
  )
226
231
  return success
232
+ except SystemExit as e:
233
+ logger.error(f"适配器 {name} 注册时尝试退出进程 (SystemExit({e.code})),已跳过。"
234
+ f"请不要使用 sys.exit() 或 raise SystemExit")
235
+ await lifecycle.submit_event(
236
+ "adapter.load",
237
+ msg=f"适配器 {name} 注册时触发 SystemExit",
238
+ data={"platform": name, "success": False},
239
+ )
240
+ return False
227
241
  except Exception as e:
228
242
  logger.error(f"适配器 {name} 注册失败: {e}")
229
243
  # 提交适配器加载失败事件
@@ -243,7 +257,7 @@ class AdapterLoader(BaseLoader):
243
257
  failed_adapters = []
244
258
  for i, result in enumerate(register_results):
245
259
  adapter_name = adapters[i]
246
- if isinstance(result, Exception) or result is False:
260
+ if isinstance(result, BaseException) or result is False:
247
261
  logger.warning(f"适配器 {adapter_name} 注册失败,已跳过")
248
262
  failed_adapters.append(adapter_name)
249
263
 
@@ -93,6 +93,9 @@ class ModuleLoader(BaseLoader):
93
93
 
94
94
  logger.print_section_separator()
95
95
 
96
+ except SystemExit as e:
97
+ logger.error(f"加载 {group_name} 时触发 SystemExit({e.code}),已阻止进程退出。"
98
+ f"请不要使用 sys.exit() 或 raise SystemExit")
96
99
  except Exception as e:
97
100
  logger.error(f"加载 {group_name} entry-points 失败: {e}")
98
101
 
@@ -191,6 +194,9 @@ class ModuleLoader(BaseLoader):
191
194
  objs[meta_name] = module_obj
192
195
  enabled_list.append(meta_name)
193
196
 
197
+ except SystemExit as e:
198
+ logger.error(f"加载模块 {meta_name} 时尝试退出进程 (SystemExit({e.code})),已跳过。"
199
+ f"请不要使用 sys.exit() 或 raise SystemExit")
194
200
  except Exception as e:
195
201
  logger.error(f"从 entry-point 加载模块 {meta_name} 失败,已跳过: {e}")
196
202
 
@@ -355,6 +361,10 @@ class ModuleLoader(BaseLoader):
355
361
  manager_instance.register(name, module_class, obj.moduleInfo)
356
362
  return True
357
363
  return False
364
+ except SystemExit as e:
365
+ logger.error(f"注册模块 {name} 时尝试退出进程 (SystemExit({e.code})),已跳过。"
366
+ f"请不要使用 sys.exit() 或 raise SystemExit")
367
+ return False
358
368
  except Exception as e:
359
369
  logger.error(f"注册模块 {name} 失败: {e}")
360
370
  return False
@@ -368,7 +378,7 @@ class ModuleLoader(BaseLoader):
368
378
  failed_modules = []
369
379
  for i, result in enumerate(register_results):
370
380
  module_name = modules[i]
371
- if isinstance(result, Exception) or result is False:
381
+ if isinstance(result, BaseException) or result is False:
372
382
  logger.warning(f"模块 {module_name} 注册失败,已跳过")
373
383
  failed_modules.append(module_name)
374
384
 
@@ -527,6 +537,9 @@ class ModuleLoader(BaseLoader):
527
537
  logger.debug(f"挂载立即加载模块到 sdk: {meta_name}")
528
538
  else:
529
539
  logger.warning(f"立即加载模块 {meta_name} 失败,已跳过")
540
+ except SystemExit as e:
541
+ logger.warning(f"初始化模块 {meta_name} 时尝试退出进程 (SystemExit({e.code})),已跳过。"
542
+ f"请不要使用 sys.exit() 或 raise SystemExit")
530
543
  except Exception as e:
531
544
  logger.warning(f"初始化模块 {meta_name} 失败,已跳过: {e}")
532
545
 
@@ -655,6 +668,17 @@ class LazyModule:
655
668
  f"懒加载模块 {object.__getattribute__(self, '_module_name')} 初始化完成"
656
669
  )
657
670
 
671
+ except SystemExit as e:
672
+ module_name = object.__getattribute__(self, "_module_name")
673
+ await lifecycle.submit_event(
674
+ "module.init",
675
+ msg=f"模块 {module_name} 尝试退出进程 (SystemExit)",
676
+ data={"module_name": module_name, "success": False},
677
+ )
678
+ logger.error(f"懒加载模块 {module_name} 尝试退出进程 (SystemExit({e.code})),已跳过。"
679
+ f"请不要使用 sys.exit() 或 raise SystemExit")
680
+ object.__setattr__(self, "_initialized", False)
681
+ object.__setattr__(self, "_init_failed", True)
658
682
  except Exception as e:
659
683
  await lifecycle.submit_event(
660
684
  "module.init",
@@ -730,6 +754,9 @@ class LazyModule:
730
754
  new_loop = asyncio.new_event_loop()
731
755
  try:
732
756
  new_loop.run_until_complete(self._initialize())
757
+ except SystemExit as e:
758
+ init_error[0] = e
759
+ object.__setattr__(self, "_init_failed", True)
733
760
  except Exception as e:
734
761
  init_error[0] = e
735
762
  object.__setattr__(self, "_init_failed", True)
@@ -784,6 +811,13 @@ class LazyModule:
784
811
  f"懒加载模块 {object.__getattribute__(self, '_module_name')} 同步初始化完成"
785
812
  )
786
813
 
814
+ except SystemExit as e:
815
+ logger.error(
816
+ f"懒加载模块 {object.__getattribute__(self, '_module_name')} 尝试退出进程 "
817
+ f"(SystemExit({e.code})),已跳过。请不要使用 sys.exit() 或 raise SystemExit"
818
+ )
819
+ object.__setattr__(self, "_initialized", False)
820
+ object.__setattr__(self, "_init_failed", True)
787
821
  except Exception as e:
788
822
  logger.error(
789
823
  f"懒加载模块 {object.__getattribute__(self, '_module_name')} 同步初始化失败: {e}"
@@ -15,6 +15,7 @@ from __future__ import annotations
15
15
 
16
16
  import asyncio
17
17
  import importlib
18
+ import os
18
19
  import sys
19
20
  from typing import TYPE_CHECKING
20
21
  from .Core.constants import UNINIT_SETTLE_DELAY_SECS, LIFECYCLE_TIMER_CORE_INIT, LIFECYCLE_TIMER_CORE_UNINIT
@@ -971,6 +972,39 @@ class SDK:
971
972
 
972
973
  return True
973
974
 
975
+ RESTART_EXIT_CODE = 42
976
+
977
+ async def hard_restart(self) -> bool:
978
+ """
979
+ 硬重启:反初始化后退出进程,由父进程(run.py)重新启动新实例
980
+
981
+ 与 restart()(热重启)的区别:
982
+ - restart(): 在同一进程内反初始化再重新初始化
983
+ - hard_restart(): 反初始化后退出进程,由父进程重新启动全新进程
984
+
985
+ 确保资源完全释放
986
+
987
+ 需要通过 epsdk run 启动才生效,否则进程退出后不会自动重启。
988
+
989
+ :return: bool 硬重启任务是否成功调度
990
+
991
+ :example:
992
+ >>> await sdk.hard_restart()
993
+ """
994
+
995
+ async def _do_hard_restart():
996
+ await asyncio.sleep(0.5)
997
+ try:
998
+ self.logger.info("[HardRestart] 开始硬重启,执行反初始化...")
999
+ await self.uninit()
1000
+ self.logger.info("[HardRestart] 反初始化完成,正在退出进程...")
1001
+ except Exception as e:
1002
+ self.logger.error(f"[HardRestart] 反初始化异常: {e}")
1003
+ os._exit(self.RESTART_EXIT_CODE)
1004
+
1005
+ asyncio.ensure_future(_do_hard_restart())
1006
+ return True
1007
+
974
1008
  async def uninit(self) -> bool:
975
1009
  """
976
1010
  SDK 反初始化
@@ -20,6 +20,7 @@ example:
20
20
  from __future__ import annotations
21
21
  import asyncio
22
22
  import importlib
23
+ import os
23
24
  import sys
24
25
  from typing import TYPE_CHECKING
25
26
  from .Core.constants import UNINIT_SETTLE_DELAY_SECS, LIFECYCLE_TIMER_CORE_INIT, LIFECYCLE_TIMER_CORE_UNINIT
@@ -170,6 +171,24 @@ class SDK:
170
171
  >>> await sdk.restart()
171
172
  """
172
173
  ...
174
+ async def hard_restart(self: object) -> bool:
175
+ """
176
+ 硬重启:反初始化后退出进程,由父进程(run.py)重新启动新实例
177
+
178
+ 与 restart()(热重启)的区别:
179
+ - restart(): 在同一进程内反初始化再重新初始化
180
+ - hard_restart(): 反初始化后退出进程,由父进程重新启动全新进程
181
+
182
+ 确保资源完全释放
183
+
184
+ 需要通过 epsdk run 启动才生效,否则进程退出后不会自动重启。
185
+
186
+ :return: bool 硬重启任务是否成功调度
187
+
188
+ :example:
189
+ >>> await sdk.hard_restart()
190
+ """
191
+ ...
173
192
  async def uninit(self: object) -> bool:
174
193
  """
175
194
  SDK 反初始化
File without changes
File without changes