Skip to content

Commit 2be12b4

Browse files
authored
Fix async install plugin dependencies for windows (#549)
1 parent baebdd9 commit 2be12b4

File tree

2 files changed

+12
-44
lines changed

2 files changed

+12
-44
lines changed

backend/app/admin/api/v1/sys/plugin.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ async def install_plugin(file: Annotated[UploadFile, File()]) -> ResponseModel:
6464
members.append(member)
6565
zf.extractall(PLUGIN_DIR, members)
6666
if os.path.exists(os.path.join(full_plugin_path, 'requirements.txt')):
67-
await install_requirements_async(False)
67+
await install_requirements_async()
6868

6969
return response_base.success()
7070

backend/plugin/tools.py

+11-43
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,15 @@
11
#!/usr/bin/env python3
22
# -*- coding: utf-8 -*-
3-
import asyncio
43
import inspect
54
import os
65
import subprocess
76
import sys
87
import warnings
98

10-
from asyncio import subprocess as async_subprocess
11-
129
import rtoml
1310

1411
from fastapi import APIRouter
12+
from starlette.concurrency import run_in_threadpool
1513

1614
from backend.core.conf import settings
1715
from backend.core.path_conf import PLUGIN_DIR
@@ -156,49 +154,19 @@ def install_requirements() -> None:
156154
continue
157155
else:
158156
try:
159-
subprocess.run([sys.executable, '-m', 'ensurepip', '--upgrade'])
160-
pip_requirements = [sys.executable, '-m', 'pip', 'install', '-r', requirements_file]
157+
ensurepip_install = [sys.executable, '-m', 'ensurepip', '--upgrade']
158+
pip_install = [sys.executable, '-m', 'pip', 'install', '-r', requirements_file]
161159
if settings.PLUGIN_PIP_CHINA:
162-
pip_requirements.extend(['-i', settings.PLUGIN_PIP_INDEX_URL])
163-
subprocess.check_call(pip_requirements)
160+
pip_install.extend(['-i', settings.PLUGIN_PIP_INDEX_URL])
161+
subprocess.check_call(ensurepip_install)
162+
subprocess.check_call(pip_install)
164163
except subprocess.CalledProcessError as e:
165-
raise PluginInjectError(f'插件 {plugin} 依赖安装失败:{e}') from e
164+
raise PluginInjectError(f'插件 {plugin} 依赖安装失败:{e.stderr}') from e
166165

167166

168-
async def install_requirements_async(wait: bool = True) -> None:
167+
async def install_requirements_async() -> None:
169168
"""
170-
异步安装插件依赖
171-
172-
:param wait: 是否等待结果并校验,开启将造成 IO 阻塞
173-
:return:
169+
异步安装插件依赖(由于 Windows 平台限制,无法实现完美的全异步方案),详情:
170+
https://stackoverflow.com/questions/44633458/why-am-i-getting-notimplementederror-with-async-and-await-on-windows
174171
"""
175-
plugins = get_plugins()
176-
for plugin in plugins:
177-
requirements_file = os.path.join(PLUGIN_DIR, plugin, 'requirements.txt')
178-
if not os.path.exists(requirements_file):
179-
continue
180-
else:
181-
ensurepip_process = await async_subprocess.create_subprocess_exec(
182-
sys.executable,
183-
'-m',
184-
'ensurepip',
185-
'--upgrade',
186-
stdout=asyncio.subprocess.PIPE,
187-
stderr=asyncio.subprocess.PIPE,
188-
)
189-
if wait:
190-
_, ensurepip_stderr = await ensurepip_process.communicate()
191-
if ensurepip_process.returncode != 0:
192-
raise PluginInjectError(f'ensurepip 安装失败:{ensurepip_stderr}')
193-
pip_requirements = [sys.executable, '-m', 'pip', 'install', '-r', requirements_file]
194-
if settings.PLUGIN_PIP_CHINA:
195-
pip_requirements.extend(['-i', settings.PLUGIN_PIP_INDEX_URL])
196-
pip_process = await async_subprocess.create_subprocess_exec(
197-
*pip_requirements,
198-
stdout=asyncio.subprocess.PIPE,
199-
stderr=asyncio.subprocess.PIPE,
200-
)
201-
if wait:
202-
_, pip_stderr = await pip_process.communicate()
203-
if pip_process.returncode != 0:
204-
raise PluginInjectError(f'插件 {plugin} 依赖包安装失败:{pip_stderr}')
172+
await run_in_threadpool(install_requirements)

0 commit comments

Comments
 (0)