fix(telemetry): silence pynvml deprecation FutureWarning on startup

Fixes #389.

The legacy `pynvml` PyPI package (since version 13.x) registers a
meta-path-finder shim — `_pynvml_redirector.py` — that prints a
`FutureWarning("The pynvml package is deprecated. Please install
nvidia-ml-py instead.")` on every `import pynvml`, even when the
caller's project doesn't depend on pynvml directly. The warning was
firing on every `jarvis --version` / `jarvis ask` / any command that
touches the telemetry path.

Two-layer fix:

1. **pyproject.toml**: switch `pynvml>=13.0.1` → `nvidia-ml-py>=12.560.30`
   in the core deps, `gpu-metrics` extra, and `energy-all` extra.
   `nvidia-ml-py` is NVIDIA's official package and ships the same
   `pynvml` module name without the redirector shim, so the warning
   doesn't fire.

2. **Defensive filters** at all four `import pynvml` sites
   (`telemetry/gpu_monitor.py`, `telemetry/energy_nvidia.py`,
   `server/research_router.py`, `evals/backends/external/_subprocess_runner.py`):
   wrap the import in a narrowly-scoped `warnings.filterwarnings("ignore",
   message=r"The pynvml package is deprecated.*", category=FutureWarning)`.
   Belt-and-suspenders for the case where `pynvml` gets pulled in
   transitively by torch / vllm / etc. — the user's environment may
   still have it installed even if our deps don't pull it in.

Verified locally:
- `uv sync` swaps pynvml → nvidia-ml-py.
- `python -c "import warnings; warnings.simplefilter('error', FutureWarning); from openjarvis.telemetry import gpu_monitor"` → no warning fires (would raise if it did).
- `jarvis --version` → clean output, no FutureWarning preceding the version string.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
krypticmouse
2026-05-23 15:20:12 +00:00
co-authored by Claude Opus 4.7
parent 2d6d6ed7bd
commit 0483f5377d
6 changed files with 51 additions and 25 deletions
+3 -3
View File
@@ -30,7 +30,7 @@ dependencies = [
"httpx>=0.27",
"openai>=1.30",
"posthog>=3.0",
"pynvml>=13.0.1",
"nvidia-ml-py>=12.560.30",
"python-telegram-bot>=22.6",
"rich>=13",
"tomli>=2.0; python_version < '3.11'",
@@ -80,10 +80,10 @@ server = [
"python-multipart>=0.0.9",
]
openhands = ["openhands-sdk>=1.0; python_version >= '3.12'"]
gpu-metrics = ["pynvml>=12.0"]
gpu-metrics = ["nvidia-ml-py>=12.560.30"]
energy-amd = ["amdsmi>=6.1"]
energy-apple = ["zeus-ml[apple]"]
energy-all = ["pynvml>=12.0", "amdsmi>=6.1", "zeus-ml[apple]"]
energy-all = ["nvidia-ml-py>=12.560.30", "amdsmi>=6.1", "zeus-ml[apple]"]
orchestrator-training = ["torch>=2.0", "transformers>=4.40"]
learning-dspy = ["dspy>=2.6"]
learning-gepa = ["gepa>=0.1"]
@@ -201,7 +201,15 @@ class _NullSampler(_Sampler):
def _try_start_nvml() -> Optional[_Sampler]:
try:
import pynvml # type: ignore
# Suppress legacy pynvml deprecation FutureWarning (#389).
import warnings as _warnings
with _warnings.catch_warnings():
_warnings.filterwarnings(
"ignore",
message=r"The pynvml package is deprecated.*",
category=FutureWarning,
)
import pynvml # type: ignore
pynvml.nvmlInit()
handle = pynvml.nvmlDeviceGetHandleByIndex(0)
+9 -1
View File
@@ -149,7 +149,15 @@ class _LiveGPUSampler:
self._t_start = 0.0
self._t_last = 0.0
try:
import pynvml # type: ignore
# Suppress legacy pynvml deprecation FutureWarning (#389).
import warnings as _warnings
with _warnings.catch_warnings():
_warnings.filterwarnings(
"ignore",
message=r"The pynvml package is deprecated.*",
category=FutureWarning,
)
import pynvml # type: ignore
pynvml.nvmlInit()
count = pynvml.nvmlDeviceGetCount()
+10 -1
View File
@@ -17,7 +17,16 @@ from openjarvis.telemetry.energy_monitor import (
logger = logging.getLogger(__name__)
try:
import pynvml
# See gpu_monitor.py for the rationale — suppress the legacy
# `pynvml` package's deprecation FutureWarning narrowly (#389).
import warnings
with warnings.catch_warnings():
warnings.filterwarnings(
"ignore",
message=r"The pynvml package is deprecated.*",
category=FutureWarning,
)
import pynvml
_PYNVML_AVAILABLE = True
except ImportError:
+14 -1
View File
@@ -12,7 +12,20 @@ from typing import Dict, Generator, List, Optional
logger = logging.getLogger(__name__)
try:
import pynvml
# The legacy `pynvml` PyPI package installs a meta-path-finder shim
# that prints a FutureWarning on every `import pynvml`, even though
# our pyproject.toml depends on `nvidia-ml-py` (the official NVIDIA
# package, same module name, no shim). The warning still fires if
# `pynvml` gets pulled in transitively by torch/vllm/etc. Suppress
# it narrowly here so user output stays clean (issue #389).
import warnings
with warnings.catch_warnings():
warnings.filterwarnings(
"ignore",
message=r"The pynvml package is deprecated.*",
category=FutureWarning,
)
import pynvml
_PYNVML_AVAILABLE = True
except ImportError:
_PYNVML_AVAILABLE = False
Generated
+6 -18
View File
@@ -4980,9 +4980,9 @@ dependencies = [
{ name = "datasets" },
{ name = "ddgs" },
{ name = "httpx" },
{ name = "nvidia-ml-py" },
{ name = "openai" },
{ name = "posthog" },
{ name = "pynvml" },
{ name = "python-telegram-bot" },
{ name = "rich" },
{ name = "tomli", marker = "python_full_version < '3.11'" },
@@ -5066,7 +5066,7 @@ docs = [
]
energy-all = [
{ name = "amdsmi" },
{ name = "pynvml" },
{ name = "nvidia-ml-py" },
{ name = "zeus-ml" },
]
energy-amd = [
@@ -5086,7 +5086,7 @@ framework-comparison = [
{ name = "polars" },
]
gpu-metrics = [
{ name = "pynvml" },
{ name = "nvidia-ml-py" },
]
inference-cloud = [
{ name = "anthropic" },
@@ -5222,6 +5222,9 @@ requires-dist = [
{ name = "mkdocstrings", extras = ["python"], marker = "extra == 'docs'", specifier = ">=0.25" },
{ name = "mlx-lm", marker = "sys_platform == 'darwin' and extra == 'inference-mlx'", specifier = ">=0.31.1" },
{ name = "numpy", marker = "extra == 'memory-faiss'", specifier = ">=1.24" },
{ name = "nvidia-ml-py", specifier = ">=12.560.30" },
{ name = "nvidia-ml-py", marker = "extra == 'energy-all'", specifier = ">=12.560.30" },
{ name = "nvidia-ml-py", marker = "extra == 'gpu-metrics'", specifier = ">=12.560.30" },
{ name = "openai", specifier = ">=1.30" },
{ name = "openai", marker = "extra == 'inference-cloud'", specifier = ">=1.30" },
{ name = "openai", marker = "extra == 'media'", specifier = ">=1.30" },
@@ -5237,9 +5240,6 @@ requires-dist = [
{ name = "pygemma", marker = "extra == 'inference-gemma'", specifier = ">=0.1.3" },
{ name = "pymessenger", marker = "extra == 'channel-messenger'", specifier = ">=0.0.7" },
{ name = "pynostr", marker = "extra == 'channel-nostr'", specifier = ">=0.6" },
{ name = "pynvml", specifier = ">=13.0.1" },
{ name = "pynvml", marker = "extra == 'energy-all'", specifier = ">=12.0" },
{ name = "pynvml", marker = "extra == 'gpu-metrics'", specifier = ">=12.0" },
{ name = "pytest", marker = "extra == 'dev'", specifier = ">=8" },
{ name = "pytest-asyncio", marker = "extra == 'dev'", specifier = ">=0.24" },
{ name = "pytest-cov", marker = "extra == 'dev'", specifier = ">=5" },
@@ -6874,18 +6874,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/aa/5e/cbcbba2be3acdc9ffce2c109f7d6296fbe2918b170a56f5742b07e000e49/pynostr-0.7.0-py3-none-any.whl", hash = "sha256:9407a64f08f29ec230ff6c5c55404fe6ad77fef1eacf409d03cfd5508ca61834", size = 37829, upload-time = "2025-08-07T05:57:12.945Z" },
]
[[package]]
name = "pynvml"
version = "13.0.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "nvidia-ml-py" },
]
sdist = { url = "https://files.pythonhosted.org/packages/5c/57/da7dc63a79f59e082e26a66ac02d87d69ea316b35b35b7a00d82f3ce3d2f/pynvml-13.0.1.tar.gz", hash = "sha256:1245991d9db786b4d2f277ce66869bd58f38ac654e38c9397d18f243c8f6e48f", size = 35226, upload-time = "2025-09-05T20:33:25.377Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/d7/4a/cac76c174bb439a0c46c9a4413fcbea5c6cabfb01879f7bbdb9fdfaed76c/pynvml-13.0.1-py3-none-any.whl", hash = "sha256:e2b20e0a501eeec951e2455b7ab444759cf048e0e13a57b08049fa2775266aa8", size = 28810, upload-time = "2025-09-05T20:33:24.13Z" },
]
[[package]]
name = "pyparsing"
version = "3.3.2"