Skip to content

Commit 2a3b04f

Browse files
Copilotharupy
andauthored
Replace virtualenv with python -m venv in virtualenv env_manager path (#20640)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: harupy <17039389+harupy@users.noreply.github.com> Co-authored-by: Harutaka Kawamura <hkawamura0130@gmail.com>
1 parent 73a3ecf commit 2a3b04f

File tree

16 files changed

+10
-60
lines changed

16 files changed

+10
-60
lines changed

.github/actions/setup-pyenv/action.yml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,3 @@ runs:
5353
shell: bash
5454
run: |
5555
pyenv --version
56-
57-
- name: Install virtualenv
58-
shell: bash
59-
run: |
60-
pip install virtualenv

dev/pyproject.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,6 @@ def build(package_type: PackageType) -> None:
337337
# Required by the mlflow.projects module, when running projects against
338338
# a remote Kubernetes cluster
339339
"kubernetes",
340-
"virtualenv",
341340
# Required for exporting metrics from the MLflow server to Prometheus
342341
# as part of the MLflow server monitoring add-on
343342
"prometheus-flask-exporter",

docs/docs/classic-ml/model/index.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1556,7 +1556,7 @@ mlflow.models.predict(
15561556

15571557
The <APILink fn="mlflow.models.predict" /> API supports the following environment managers to create the virtual environment for prediction:
15581558

1559-
- [virtualenv](https://virtualenv.pypa.io/en/latest/): The default environment manager.
1559+
- `virtualenv`: The default environment manager. Uses Python's built-in [venv](https://docs.python.org/3/library/venv.html) module to create virtual environments.
15601560
- [uv](https://docs.astral.sh/uv/): An **extremely fast** environment manager written in Rust. **This is an experimental feature since MLflow 2.20.0.**
15611561
- [conda](https://docs.conda.io/projects/conda/): uses conda to create environment.
15621562
- `local`: uses the current environment to run the model. Note that `pip_requirements_override` is not supported in this mode.

libs/skinny/pyproject.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ extras = [
6262
"azureml-core>=1.2.0",
6363
"pysftp",
6464
"kubernetes",
65-
"virtualenv",
6665
"prometheus-flask-exporter",
6766
]
6867
db = ["PyMySQL", "psycopg2-binary", "pymssql"]

mlflow/models/docker_utils.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
PYTHON_SLIM_BASE_IMAGE = "python:{version}-slim"
1616

1717

18-
SETUP_PYENV_AND_VIRTUALENV = r"""# Setup pyenv
18+
SETUP_PYENV = r"""# Setup pyenv
1919
RUN DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get -y install tzdata \
2020
libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm \
2121
libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev
@@ -35,7 +35,6 @@
3535
&& ln -s -f $(which python3.10) /usr/bin/python \
3636
&& wget https://bootstrap.pypa.io/get-pip.py -O /tmp/get-pip.py \
3737
&& python /tmp/get-pip.py
38-
RUN pip install virtualenv
3938
""" # noqa: E501
4039

4140
_DOCKERFILE_TEMPLATE = """# Build an image that can serve mlflow models.
@@ -112,9 +111,7 @@ def generate_dockerfile(
112111
"--no-install-recommends wget curl nginx ca-certificates bzip2 build-essential cmake "
113112
"git-core\n\n"
114113
)
115-
setup_python_venv_steps += (
116-
SETUP_MINICONDA if env_manager == em.CONDA else SETUP_PYENV_AND_VIRTUALENV
117-
)
114+
setup_python_venv_steps += SETUP_MINICONDA if env_manager == em.CONDA else SETUP_PYENV
118115
if install_java is not False:
119116
jdk_ver = MLFLOW_DOCKER_OPENJDK_VERSION.get()
120117
setup_java_steps = (

mlflow/utils/cli_args.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ def _create_env_manager_option(help_string, default=None):
101101
102102
\b
103103
- local: use the local environment
104-
- virtualenv: use virtualenv (and pyenv for Python version management)
104+
- virtualenv: use venv (and pyenv for Python version management)
105105
- uv: use uv
106106
- conda: use conda
107107
@@ -116,7 +116,7 @@ def _create_env_manager_option(help_string, default=None):
116116
117117
\b
118118
- local: use the local environment
119-
- virtualenv: use virtualenv (and pyenv for Python version management)
119+
- virtualenv: use venv (and pyenv for Python version management)
120120
- uv: use uv
121121
- conda: use conda
122122
@@ -136,7 +136,7 @@ def _create_env_manager_option(help_string, default=None):
136136
137137
\b
138138
- local: use the local environment
139-
- virtualenv: use virtualenv (and pyenv for Python version management)
139+
- virtualenv: use venv (and pyenv for Python version management)
140140
- uv: use uv
141141
- conda: use conda
142142

mlflow/utils/virtualenv.py

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
import os
33
import re
44
import shutil
5-
import sys
65
import tempfile
76
import uuid
87
from pathlib import Path
@@ -65,25 +64,6 @@ def _validate_pyenv_is_available():
6564
)
6665

6766

68-
def _is_virtualenv_available():
69-
"""
70-
Returns True if virtualenv is available, otherwise False.
71-
"""
72-
return shutil.which("virtualenv") is not None
73-
74-
75-
def _validate_virtualenv_is_available():
76-
"""
77-
Validates virtualenv is available. If not, throws an `MlflowException` with a brief instruction
78-
on how to install virtualenv.
79-
"""
80-
if not _is_virtualenv_available():
81-
raise MlflowException(
82-
"Could not find the virtualenv binary. Run `pip install virtualenv` to install "
83-
"virtualenv."
84-
)
85-
86-
8767
_SEMANTIC_VERSION_REGEX = re.compile(r"^([0-9]+)\.([0-9]+)\.([0-9]+)$")
8868

8969

@@ -270,14 +250,7 @@ def _create_virtualenv(
270250
python_env.python, pyenv_root=python_install_dir, capture_output=capture_output
271251
)
272252
_logger.info(f"Creating a new environment in {env_dir} with {python_bin_path}")
273-
env_creation_cmd = [
274-
sys.executable,
275-
"-m",
276-
"virtualenv",
277-
"--python",
278-
python_bin_path,
279-
env_dir,
280-
]
253+
env_creation_cmd = [python_bin_path, "-m", "venv", env_dir]
281254
install_deps_cmd_prefix = "python -m pip install"
282255
elif env_manager == em.UV:
283256
_logger.info(
@@ -418,7 +391,6 @@ def _get_or_create_virtualenv(
418391
"""
419392
if env_manager == em.VIRTUALENV:
420393
_validate_pyenv_is_available()
421-
_validate_virtualenv_is_available()
422394

423395
local_model_path = Path(local_model_path)
424396
python_env = _get_python_env(local_model_path)

pyproject.release.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ extras = [
6464
"azureml-core>=1.2.0",
6565
"pysftp",
6666
"kubernetes",
67-
"virtualenv",
6867
"prometheus-flask-exporter",
6968
]
7069
db = ["PyMySQL", "psycopg2-binary", "pymssql"]

pyproject.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ extras = [
8181
"azureml-core>=1.2.0",
8282
"pysftp",
8383
"kubernetes",
84-
"virtualenv",
8584
"prometheus-flask-exporter",
8685
]
8786
db = ["PyMySQL", "psycopg2-binary", "pymssql"]

tests/pyfunc/test_virtualenv.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,13 @@
1515
from mlflow.environment_variables import MLFLOW_ENV_ROOT
1616
from mlflow.pyfunc.scoring_server import CONTENT_TYPE_JSON
1717
from mlflow.utils.environment import _PYTHON_ENV_FILE_NAME, _REQUIREMENTS_FILE_NAME
18-
from mlflow.utils.virtualenv import (
19-
_is_pyenv_available,
20-
_is_virtualenv_available,
21-
)
18+
from mlflow.utils.virtualenv import _is_pyenv_available
2219

2320
from tests.helper_functions import pyfunc_serve_and_score_model
2421

2522
pytestmark = pytest.mark.skipif(
26-
not (_is_pyenv_available() and _is_virtualenv_available()),
27-
reason="requires pyenv and virtualenv",
23+
not _is_pyenv_available(),
24+
reason="requires pyenv",
2825
)
2926

3027
TEST_DIR = "tests"

0 commit comments

Comments
 (0)