pycoze 0.1.445__py3-none-any.whl → 0.1.447__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.
- pycoze/reference/__init__.py +1 -1
- pycoze/reference/fn.py +1 -1
- pycoze/reference/lib.py +4 -0
- pycoze/utils/process.py +133 -0
- pycoze/utils/socket.py +2 -1
- {pycoze-0.1.445.dist-info → pycoze-0.1.447.dist-info}/METADATA +1 -1
- {pycoze-0.1.445.dist-info → pycoze-0.1.447.dist-info}/RECORD +10 -9
- {pycoze-0.1.445.dist-info → pycoze-0.1.447.dist-info}/LICENSE +0 -0
- {pycoze-0.1.445.dist-info → pycoze-0.1.447.dist-info}/WHEEL +0 -0
- {pycoze-0.1.445.dist-info → pycoze-0.1.447.dist-info}/top_level.txt +0 -0
pycoze/reference/__init__.py
CHANGED
@@ -2,4 +2,4 @@ from .bot import ref_bot
|
|
2
2
|
from .tool import ref_tools
|
3
3
|
from .workflow import ref_workflow
|
4
4
|
from .lib import call_func
|
5
|
-
from .fn import single_process, multi_process, generator_function, compatibility,
|
5
|
+
from .fn import single_process, multi_process, generator_function, compatibility, global_process
|
pycoze/reference/fn.py
CHANGED
pycoze/reference/lib.py
CHANGED
pycoze/utils/process.py
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
import asyncio
|
2
|
+
import os
|
3
|
+
import sys
|
4
|
+
import atexit
|
5
|
+
import time
|
6
|
+
import chardet
|
7
|
+
|
8
|
+
|
9
|
+
def better_kill(process, raiseError: bool):
|
10
|
+
"""优雅地终止进程,如果超时则强制终止"""
|
11
|
+
try:
|
12
|
+
process.terminate() # 先尝试优雅终止
|
13
|
+
time.sleep(5) # 等待5秒
|
14
|
+
except asyncio.TimeoutError:
|
15
|
+
try:
|
16
|
+
process.kill() # 如果超时,强制终止
|
17
|
+
except:
|
18
|
+
if raiseError:
|
19
|
+
raise
|
20
|
+
else:
|
21
|
+
pass
|
22
|
+
except Exception as e:
|
23
|
+
# print(f"Error while terminating process: {e}")
|
24
|
+
if raiseError:
|
25
|
+
raise
|
26
|
+
else:
|
27
|
+
pass
|
28
|
+
|
29
|
+
|
30
|
+
|
31
|
+
async def read_stream(stream, log, separator=b'\n'):
|
32
|
+
def log_func(data):
|
33
|
+
try:
|
34
|
+
data = data.decode().strip()
|
35
|
+
log(data)
|
36
|
+
except:
|
37
|
+
try:
|
38
|
+
encoding = chardet.detect(data)['encoding']
|
39
|
+
data = data.decode(encoding).strip()
|
40
|
+
finally:
|
41
|
+
log(data)
|
42
|
+
|
43
|
+
while True:
|
44
|
+
try:
|
45
|
+
line = await stream.readuntil(separator)
|
46
|
+
log_func(line)
|
47
|
+
except asyncio.IncompleteReadError as e:
|
48
|
+
# If the stream ends without a separator, output the remaining content
|
49
|
+
if e.partial:
|
50
|
+
log_func(e.partial)
|
51
|
+
break
|
52
|
+
except asyncio.LimitOverrunError as e:
|
53
|
+
# If the separator is found but not within the limit, read the chunk
|
54
|
+
chunk = await stream.read(e.consumed)
|
55
|
+
log_func(chunk)
|
56
|
+
|
57
|
+
|
58
|
+
|
59
|
+
|
60
|
+
async def execute_script(script_path, *args, cwd=None, env=None):
|
61
|
+
cwd = cwd or os.path.dirname(script_path)
|
62
|
+
process = await asyncio.create_subprocess_exec(
|
63
|
+
sys.executable,
|
64
|
+
"-u",
|
65
|
+
script_path,
|
66
|
+
*args,
|
67
|
+
cwd=cwd,
|
68
|
+
env=env,
|
69
|
+
stdout=asyncio.subprocess.PIPE,
|
70
|
+
stderr=asyncio.subprocess.PIPE,
|
71
|
+
)
|
72
|
+
return process
|
73
|
+
|
74
|
+
|
75
|
+
async def execute_script_and_block(script_path, log, *args, cwd=None, env=None):
|
76
|
+
try:
|
77
|
+
# 执行脚本
|
78
|
+
process = await execute_script(script_path, *args, cwd=cwd, env=env)
|
79
|
+
except Exception as e:
|
80
|
+
better_kill(process, False)
|
81
|
+
raise Exception(f"Failed to execute script: {e}")
|
82
|
+
|
83
|
+
try:
|
84
|
+
# 开始并行读取 stdout 和 stderr
|
85
|
+
stdout_task = asyncio.create_task(read_stream(process.stdout, log))
|
86
|
+
stderr_task = asyncio.create_task(read_stream(process.stderr, log))
|
87
|
+
|
88
|
+
# 注册atexit处理程序
|
89
|
+
async def cleanup():
|
90
|
+
better_kill(process, False)
|
91
|
+
stdout_task.cancel()
|
92
|
+
stderr_task.cancel()
|
93
|
+
atexit.register(cleanup)
|
94
|
+
|
95
|
+
# 等待进程完成
|
96
|
+
return_code = await process.wait()
|
97
|
+
|
98
|
+
# 等待读取任务完成
|
99
|
+
await stdout_task
|
100
|
+
await stderr_task
|
101
|
+
|
102
|
+
except Exception as e:
|
103
|
+
better_kill(process, False)
|
104
|
+
stdout_task.cancel()
|
105
|
+
stderr_task.cancel()
|
106
|
+
raise Exception(f"Error during script execution or stream reading: {e}")
|
107
|
+
|
108
|
+
# 检查返回码
|
109
|
+
if return_code != 0:
|
110
|
+
better_kill(process, False)
|
111
|
+
raise Exception("Error executing script, return code: {}".format(return_code))
|
112
|
+
|
113
|
+
# 如果一切正常,返回成功
|
114
|
+
return "success"
|
115
|
+
|
116
|
+
|
117
|
+
|
118
|
+
async def execute_script_no_block(script_path, log, *args, cwd=None, env=None):
|
119
|
+
process = await execute_script(script_path, *args, cwd=cwd, env=env)
|
120
|
+
|
121
|
+
# Start reading stdout and stderr in parallel
|
122
|
+
stdout_task = asyncio.create_task(read_stream(process.stdout, log))
|
123
|
+
stderr_task = asyncio.create_task(read_stream(process.stderr, log))
|
124
|
+
|
125
|
+
# Register atexit handler to ensure process cleanup
|
126
|
+
def cleanup():
|
127
|
+
better_kill(process, False)
|
128
|
+
stdout_task.cancel()
|
129
|
+
stderr_task.cancel()
|
130
|
+
|
131
|
+
atexit.register(cleanup)
|
132
|
+
|
133
|
+
return process, stdout_task, stderr_task
|
pycoze/utils/socket.py
CHANGED
@@ -12,7 +12,8 @@ class TcpSocket:
|
|
12
12
|
self.is_connected = True
|
13
13
|
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
14
14
|
if params is not None:
|
15
|
-
|
15
|
+
if "tcpPort" in params:
|
16
|
+
self.socket.connect(("localhost", int(params["tcpPort"])))
|
16
17
|
|
17
18
|
def post(self, subject, message):
|
18
19
|
subject = "python-event:" + subject
|
@@ -16,10 +16,10 @@ pycoze/bot/lib.py,sha256=RivPA2f5fqzqbW6jL0sx9X9pwgFPxwkk8lt62CWvaZo,7255
|
|
16
16
|
pycoze/bot/message.py,sha256=udnIi-h4QgGzkbr_5VcAsVGjoLp9wXJSfBCeuOz7_Bk,802
|
17
17
|
pycoze/bot/prompt.md,sha256=UtwZ31wFvNtvM9ZTA4BU2yT1Rb-qnUdU3Ny1O37Tt3Q,14077
|
18
18
|
pycoze/bot/tools.py,sha256=BWMdwvqLzvcyaW38lzxUWtc0K1V-C_qPSEZ3OKlAQvU,11108
|
19
|
-
pycoze/reference/__init__.py,sha256=
|
19
|
+
pycoze/reference/__init__.py,sha256=u25FWJnOBWsDRoL8_O4jzW4tkJrHT3Sqp9EGCxUhS3E,211
|
20
20
|
pycoze/reference/bot.py,sha256=UZK24Qm8kpqpwXJy_zNZeTEEDee05luXdSBeUm0NCt0,2029
|
21
|
-
pycoze/reference/fn.py,sha256=
|
22
|
-
pycoze/reference/lib.py,sha256=
|
21
|
+
pycoze/reference/fn.py,sha256=ZXnG2ctbHMgr3quQp-4bpnErIkuT-t2_ToSET5LTLbc,750
|
22
|
+
pycoze/reference/lib.py,sha256=R-0T2QjxCUSF7K7XQtKaGm2n7uVptW4BnGu8s1QjMe0,3835
|
23
23
|
pycoze/reference/tool.py,sha256=kv5Ww8fZVECNJfE7Ku5M88jqHgSO0yTF0S6eijQu9KE,1104
|
24
24
|
pycoze/reference/workflow.py,sha256=59teXvIM_kOa-rJMLudJaJb9FBumYEmOzMT5jifKqDY,1337
|
25
25
|
pycoze/ui/__init__.py,sha256=uaXet23wUk64TcZjpBX8qOx4aUhwA_ucrmcxy7Q4Qr4,929
|
@@ -30,10 +30,11 @@ pycoze/ui/ui_def.py,sha256=lGWZGpzRoegP34D562PvK0EJHrmVZrlHW1JjsIG9A9Q,4521
|
|
30
30
|
pycoze/utils/__init__.py,sha256=H-2KRUsUG47owL0sbD1KwDOuRm-j_0K4RkeNhzr7ISo,319
|
31
31
|
pycoze/utils/arg.py,sha256=jop1tBfe5hYkHW1NSpCeaZBEznkgguBscj_7M2dWfrs,503
|
32
32
|
pycoze/utils/env.py,sha256=5pWlXfM1F5ZU9hhv1rHlDEanjEW5wf0nbyez9bNRqqA,559
|
33
|
-
pycoze/utils/
|
33
|
+
pycoze/utils/process.py,sha256=U2MURGmxfyWBqdbKfy5UvyV17M40B6HHlNELgWfgrTE,3824
|
34
|
+
pycoze/utils/socket.py,sha256=4Wm4LlwdWXC_kAV0NnZbUc0Y3Kc6KRMyFRqSw79u-9w,2468
|
34
35
|
pycoze/utils/text_or_file.py,sha256=gpxZVWt2DW6YiEg_MnMuwg36VNf3TX383QD_1oZNB0Y,551
|
35
|
-
pycoze-0.1.
|
36
|
-
pycoze-0.1.
|
37
|
-
pycoze-0.1.
|
38
|
-
pycoze-0.1.
|
39
|
-
pycoze-0.1.
|
36
|
+
pycoze-0.1.447.dist-info/LICENSE,sha256=QStd_Qsd0-kAam_-sOesCIp_uKrGWeoKwt9M49NVkNU,1090
|
37
|
+
pycoze-0.1.447.dist-info/METADATA,sha256=EBKllPIWr_-30XTHbUZMMDDRJcNKvXDU_G4RUjvs-2c,854
|
38
|
+
pycoze-0.1.447.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
39
|
+
pycoze-0.1.447.dist-info/top_level.txt,sha256=76dPeDhKvOCleL3ZC5gl1-y4vdS1tT_U1hxWVAn7sFo,7
|
40
|
+
pycoze-0.1.447.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|