繁体   English   中英

makefile中virtualenv的使用方法

[英]How to use virtualenv in makefile

我想在指定的 virtualenv 上执行多个操作。

例如命令

make install

相当于

source path/to/virtualenv/bin/activate
pip install -r requirements.txt

是否可以?

我喜欢使用仅在requirements.txt更改时运行的东西:

这假定源文件正在project在项目的根目录下,并且测试是在project/test (您应该更改project以匹配您的实际项目名称。)

venv: venv/touchfile

venv/touchfile: requirements.txt
    test -d venv || virtualenv venv
    . venv/bin/activate; pip install -Ur requirements.txt
    touch venv/touchfile

test: venv
    . venv/bin/activate; nosetests project/test

clean:
    rm -rf venv
    find -iname "*.pyc" -delete
  • 运行makerequirements.txt安装包。
  • 运行make test来运行您的测试(如果您的测试在其他地方,您可以更新此命令)。
  • 运行make clean以删除所有工件。

在 make 中,您可以将 shell 作为命令运行。 在这个 shell 中,您可以执行在从命令行启动的 shell 中可以执行的所有操作。 例子:

install:
    ( \
       source path/to/virtualenv/bin/activate; \
       pip install -r requirements.txt; \
    )

必须注意; \\

开括号和闭括号之间的所有内容都将在外壳的单个实例中完成。

通常make在不同的子 shell 中运行配方中的每个命令。 但是,设置.ONESHELL:将在同一.ONESHELL:运行配方中的所有命令,允许您激活 virtualenv,然后在其中运行命令。

请注意.ONESHELL:适用于整个 Makefile,而不仅仅是单个配方。 它可能会改变现有命令的行为,完整文档中可能出现的错误的详细信息。 这不会让你激活一个 virtualenv 以在 Makefile 之外使用,因为命令仍然在子 shell 内运行。

参考文档: https : //www.gnu.org/software/make/manual/html_node/One-Shell.html

例子:

.ONESHELL:

.PHONY: install
install:
    source path/to/virtualenv/bin/activate
    pip install -r requirements.txt

我很幸运。

install:
    source ./path/to/bin/activate; \
    pip install -r requirements.txt; \

这是运行您想要在 virtualenv 中运行的东西的另一种方法。

BIN=venv/bin/

install:
    $(BIN)pip install -r requirements.txt

run:
    $(BIN)python main.py

PS:这不会激活 virtualenv,但会完成任务。 希望你觉得它干净而且有用。

基于上面的答案(感谢@Saurabh 和@oneself!)我编写了一个可重用的 Makefile,负责创建虚拟环境并保持更新: https : //github.com/sio/Makefile.venv

它通过在 virtualenv 中引用正确的可执行文件来工作,并且不依赖于“激活”shell 脚本。 下面是一个例子:

test: venv
    $(VENV)/python -m unittest

include Makefile.venv

考虑到 Windows 和其他操作系统之间的差异,Makefile.venv 应该可以在任何提供 Python 和 make 的操作系统上正常工作。

您还可以使用名为“VIRTUALENVWRAPPER_SCRIPT”的环境变量。 像这样:

install:
    ( \
       source $$VIRTUALENVWRAPPER_SCRIPT; \
       pip install -r requirements.txt; \
    )

我喜欢设置我的 Makefile 以便它使用venv目录(如果存在),但默认使用 PATH。

对于本地开发,我喜欢使用venv ,所以我运行:

make venv    # /usr/bin/python3 -m venv venv
make deps    # .venv/bin/python -m pip install -r requirements.txt
make test    # .venv/bin/python -m tox

如果我安装到容器中,或者安装到我的机器中,我可能会绕过虚拟环境:

make deps     # /usr/bin/python3 -m pip install -r requirements.txt
make test     # /usr/bin/python3 -m tox
make build    # /usr/bin/python3 -m build --wheel
make install  # /usr/bin/python3 -m pip install dist/*.whl

设置

在 Makefile 的顶部,定义这两个变量:

# If `venv/bin/python` exists, it is used. If not, use PATH to find python.
SYSTEM_PYTHON  = $(or $(shell which python3), $(shell which python))
PYTHON         = $(or $(wildcard venv/bin/python), $(SYSTEM_PYTHON))

其中评估为:

# If "venv" dir exists:
SYSTEM_PYTHON = /usr/bin/python3
PYTHON        = .venv/bin/python

# If "venv" dir does not exist:
SYSTEM_PYTHON = /usr/bin/python3
PYTHON        = /usr/bin/python3

注意: /usr/bin/python3可能是您系统上的其他内容,具体取决于您的PATH

在您的 makefile 中,像这样运行可执行文件(包括 pip):

$(PYTHON) -m tox

您可能想要创建一个venv目标来创建venv目录:

venv:
    rm -rf $(VENV)
    $(SYSTEM_PYTHON) -m venv $(VENV)

还有一个deps目标来安装依赖项:

deps:
    $(PYTHON) -m pip install -r requirements.txt

例子

这是我的 Makefile:

MAKEFLAGS     = --no-print-directory --no-builtin-rules
.DEFAULT_GOAL = all

# Variables
PACKAGE = mypackage

# If virtualenv exists, use it. If not, use PATH to find
SYSTEM_PYTHON  = $(or $(shell which python3), $(shell which python))
PYTHON         = $(or $(wildcard venv/bin/python), $(SYSTEM_PYTHON))

all: test build

.PHONY: all

## Environment

venv:
    rm -rf venv
    $(SYSTEM_PYTHON) -m venv venv

deps:
    $(PYTHON) -m pip install --upgrade pip -r requirements.txt -r requirements_dev.txt

.PHONY: venv deps

## Lint, test

test:
    $(PYTHON) -m tox

dev/test:
    $(PYTHON) -m tox -e py38

dev/lint:
    $(PYTHON) -m tox -e lint

dev/lintfix:
    $(PYTHON) -m black $(PACKAGE) tests setup.py

.PHONY: test dev/test dev/lint dev/lintfix

## Build, install

build:
    $(PYTHON) -m build --sdist
    $(PYTHON) -m build --wheel

install:
    $(PYTHON) -m pip install dist/$(PACKAGE)-*.whl

.PHONY: build install

## Clean

clean:
    rm -rf .out .pytest_cache .tox *.egg-info dist build

.PHONY: clean

聚会有点晚了,但这是我通常的设置:

# system python interpreter. used only to create virtual environment
PY = python3
VENV = venv
BIN=$(VENV)/bin

# make it work on windows too
ifeq ($(OS), Windows_NT)
    BIN=$(VENV)/Scripts
    PY=python
endif


all: lint test

$(VENV): requirements.txt requirements-dev.txt setup.py
    $(PY) -m venv $(VENV)
    $(BIN)/pip install --upgrade -r requirements.txt
    $(BIN)/pip install --upgrade -r requirements-dev.txt
    $(BIN)/pip install -e .
    touch $(VENV)

.PHONY: test
test: $(VENV)
    $(BIN)/pytest

.PHONY: lint
lint: $(VENV)
    $(BIN)/flake8

.PHONY: release
release: $(VENV)
    $(BIN)/python setup.py sdist bdist_wheel upload

clean:
    rm -rf $(VENV)
    find . -type f -name *.pyc -delete
    find . -type d -name __pycache__ -delete

我对此做了一些更详细的文章,但基本上这个想法是你使用系统的Python来创建虚拟环境,而对于其他目标,只需在你的命令前面加上指向binScripts目录的$(BIN)变量你的venv。 这相当于activate function。

我发现在$PATH之前添加$VIRTUAL_ENV是最好的方法:

  • 无需通过activate和约束自己来混淆食谱; 链接
  • 可以像往常一样简单地使用python ,它将返回到系统 Python
    • 不需要第三方包
    • 兼容 Windows (如果使用bash )和 POSIX
# SYSTEM_PYTHON defaults to Python on the local machine
SYSTEM_PYTHON = $(shell which python)

REPO_ROOT = $(shell pwd)
# Specify with REPO_ROOT so recipes can safely change directories
export VIRTUAL_ENV := ${REPO_ROOT}/venv
# bin = POSIX, Scripts = Windows
export PATH := ${VIRTUAL_ENV}/bin:${VIRTUAL_ENV}/Scripts:${PATH}

对于那些对示例用法感兴趣的人:

# SEE: http://redsymbol.net/articles/unofficial-bash-strict-mode/
SHELL=/bin/bash -euo pipefail
.DEFAULT_GOAL := fresh-install

show-python:    ## Show path to python and version.
    @echo -n "python location: "
    @python -c "import sys; print(sys.executable, end='')"
    @echo -n ", version: "
    @python -c "import platform; print(platform.python_version())"

show-venv: show-python
show-venv:  ## Show output of python -m pip list.
    python -m pip list

install: show-python
install:    ## Install all dev dependencies into a local virtual environment.
    python -m pip install -r requirements-dev.txt --progress-bar off

fresh-install:  ## Run a fresh install into a local virtual environment.
    -rm -rf venv
    $(SYSTEM_PYTHON) -m venv venv
    @$(MAKE) install

你应该使用这个,它现在对我有用。

report.ipynb : merged.ipynb
    ( bash -c "source ${HOME}/anaconda3/bin/activate py27; which -a python; \
        jupyter nbconvert \
        --to notebook \
        --ExecutePreprocessor.kernel_name=python2 \
        --ExecutePreprocessor.timeout=3000 \
        --execute merged.ipynb \
        --output=$< $<" )

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM