Skip to content

Commit 00bc02f

Browse files
authored
Fix the venv pip availability in Linux (#893)
* Fix the venv pip availability in Linux * Remove pip install timeout
1 parent 7e9ce2e commit 00bc02f

File tree

2 files changed

+78
-4
lines changed

2 files changed

+78
-4
lines changed

backend/core/conf.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ class Settings(BaseSettings):
189189
# Plugin 配置
190190
PLUGIN_PIP_CHINA: bool = True
191191
PLUGIN_PIP_INDEX_URL: str = 'https://mirrors.aliyun.com/pypi/simple/'
192+
PLUGIN_PIP_MAX_RETRY: int = 3
192193
PLUGIN_REDIS_PREFIX: str = 'fba:plugin'
193194

194195
# I18n 配置

backend/plugin/tools.py

Lines changed: 77 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,62 @@ def build_final_router() -> APIRouter:
286286
return main_router
287287

288288

289-
def install_requirements(plugin: str | None) -> None:
289+
def _ensure_pip_available() -> bool:
290+
"""确保 pip 在虚拟环境中可用"""
291+
try:
292+
result = subprocess.run([sys.executable, '-m', 'pip', '--version'], capture_output=True, text=True)
293+
if result.returncode == 0:
294+
return True
295+
except (subprocess.TimeoutExpired, subprocess.SubprocessError, FileNotFoundError):
296+
pass
297+
298+
# 尝试使用 ensurepip
299+
try:
300+
subprocess.check_call(
301+
[sys.executable, '-m', 'ensurepip', '--default-pip'],
302+
stdout=subprocess.DEVNULL,
303+
stderr=subprocess.DEVNULL,
304+
)
305+
result = subprocess.run([sys.executable, '-m', 'pip', '--version'], capture_output=True, text=True)
306+
if result.returncode == 0:
307+
return True
308+
except (subprocess.CalledProcessError, subprocess.TimeoutExpired, subprocess.SubprocessError, FileNotFoundError):
309+
pass
310+
311+
# 尝试下载并安装
312+
try:
313+
import os
314+
import tempfile
315+
316+
import httpx
317+
318+
try:
319+
with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False) as f:
320+
with httpx.Client(timeout=3) as client:
321+
get_pip_url = 'https://bootstrap.pypa.io/get-pip.py'
322+
response = client.get(get_pip_url)
323+
response.raise_for_status()
324+
f.write(response.text)
325+
temp_file = f.name
326+
except Exception: # noqa: ignore
327+
return False
328+
329+
try:
330+
subprocess.check_call([sys.executable, temp_file], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
331+
result = subprocess.run([sys.executable, '-m', 'pip', '--version'], capture_output=True, text=True)
332+
return result.returncode == 0
333+
finally:
334+
try:
335+
os.unlink(temp_file)
336+
except OSError:
337+
pass
338+
except Exception: # noqa: ignore
339+
pass
340+
341+
return False
342+
343+
344+
def install_requirements(plugin: str | None) -> None: # noqa: C901
290345
"""
291346
安装插件依赖
292347
@@ -316,12 +371,30 @@ def install_requirements(plugin: str | None) -> None:
316371

317372
if missing_dependencies:
318373
try:
319-
ensurepip_install = [sys.executable, '-m', 'ensurepip', '--upgrade']
374+
if not _ensure_pip_available():
375+
raise PluginInstallError(f'pip 安装失败,无法继续安装插件 {plugin} 依赖')
376+
320377
pip_install = [sys.executable, '-m', 'pip', 'install', '-r', requirements_file]
321378
if settings.PLUGIN_PIP_CHINA:
322379
pip_install.extend(['-i', settings.PLUGIN_PIP_INDEX_URL])
323-
subprocess.check_call(ensurepip_install, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
324-
subprocess.check_call(pip_install, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
380+
381+
max_retries = settings.PLUGIN_PIP_MAX_RETRY
382+
for attempt in range(max_retries):
383+
try:
384+
subprocess.check_call(
385+
pip_install,
386+
stdout=subprocess.DEVNULL,
387+
stderr=subprocess.DEVNULL,
388+
)
389+
break
390+
except subprocess.TimeoutExpired:
391+
if attempt == max_retries - 1:
392+
raise PluginInstallError(f'插件 {plugin} 依赖安装超时')
393+
continue
394+
except subprocess.CalledProcessError as e:
395+
if attempt == max_retries - 1:
396+
raise PluginInstallError(f'插件 {plugin} 依赖安装失败:{e}') from e
397+
continue
325398
except subprocess.CalledProcessError as e:
326399
raise PluginInstallError(f'插件 {plugin} 依赖安装失败:{e}') from e
327400

0 commit comments

Comments
 (0)