Python 如何在 systemd 服务单元中启用 virtualenv?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/37211115/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 19:02:23  来源:igfitidea点击:

How to enable a virtualenv in a systemd service unit?

pythonenvironment-variablesvirtualenv

提问by guettli

I want to "activate" a virtualenv in a systemd service file.

我想在 systemd 服务文件中“激活”一个 virtualenv。

I would like avoid to have a shell process between the systemd process and the python interpreter.

我想避免在 systemd 进程和 python 解释器之间有一个 shell 进程。

My current solution looks like this:

我目前的解决方案是这样的:

[Unit]
Description=fooservice
After=syslog.target network.target

[Service]
Type=simple
User=fooservice
WorkingDirectory={{ venv_home }}
ExecStart={{ venv_home }}/fooservice --serve-in-foreground
Restart=on-abort
EnvironmentFile=/etc/sysconfig/fooservice.env

[Install]
WantedBy=multi-user.target

/etc/sysconfig/fooservice.env

/etc/sysconfig/fooservice.env

PATH={{ venv_home }}/bin:/usr/local/bin:/usr/bin:/bin
PYTHONIOENCODING=utf-8
PYTHONPATH={{ venv_home }}/...
VIRTUAL_ENV={{ venv_home }}

But I am having trouble. I get ImportErrors since some enties in sys.path are missing.

但我遇到了麻烦。由于缺少 sys.path 中的某些条目,我收到了 ImportErrors。

回答by Nils Werner

The virtualenv is "baked into the Python interpreter in the virtualenv". This means you can launch pythonor console_scriptsdirectly in that virtualenv and don't need to activate the virtualenv first or manage PATHyourself.:

virtualenv 被“烘焙到 virtualenv 中的 Python 解释器中”。这意味着您可以启动pythonconsole_scripts直接在该 virtualenv 中启动,而无需先激活 virtualenv 或自行管理PATH。:

ExecStart={{ venv_home }}/bin/fooservice --serve-in-foreground

or

或者

ExecStart={{ venv_home }}/bin/python {{ venv_home }}/fooservice.py --serve-in-foreground

and remove the EnvironmentFileentry.

并删除EnvironmentFile条目。

To verify that it is indeed correct you can check sys.pathby running

要验证它确实正确,您可以sys.path通过运行来检查

{{ venv_home }}/bin/python -m site

and comparing the output to

并将输出与

python -m site

回答by Alexis Lessard

While the path for libraries is indeed baked into the python interpreter of the virtualenv, I've had issues with python tools that were using binaries installed in that virtualenv. For instance, my apache airflow service wouldn't work because it couldn't find the gunicornbinary. To work around this, here's my ExecStartinstruction, with an Environmentinstruction (which sets an environment variable for the service alone).

虽然库的路径确实被嵌入到 virtualenv 的 python 解释器中,但我在使用安装在该 virtualenv 中的二进制文件的 python 工具方面遇到了问题。例如,我的 apache 气流服务无法工作,因为它找不到gunicorn二进制文件。为了解决这个问题,这是我的ExecStart指令,有一条Environment指令(它为服务单独设置一个环境变量)。

ExecStart={{ virtualenv }}/bin/python {{ virtualenv }}/bin/airflow webserver
Environment="PATH={{ virtualenv }}/bin:{{ ansible_env.PATH }}"

ExecStartexplicitly uses the python interpreter of the virtualenv. I'm also adding a PATHvariable, which adds the binary folder of the virtualenv before the system PATH. That way, I get the desired python libraries as well as binaries.

ExecStart显式使用 virtualenv 的 python 解释器。我还添加了一个PATH变量,它在 system 之前添加了 virtualenv 的二进制文件夹PATH。这样,我就获得了所需的 Python 库和二进制文件。

Note that I'm using ansible to build this service, ergo the curly braces of jinja2.

请注意,我使用 ansible 来构建此服务,因此使用 jinja2 的花括号。

回答by Sebastian Cardona Osorio

In my case I just tried to add environment variables required for Flask, for instance

就我而言,我只是尝试添加 Flask 所需的环境变量,例如

[Service]
Environment="PATH=/xx/yy/zz/venv/bin"
Environment="FLASK_ENV=development"
Environment="APP_SETTINGS=config.DevelopmentConfig"

I was using virtualenv so /xx/yy/zz/venv/binis the path of virtualenv folder.

我使用的是 virtualenv /xx/yy/zz/venv/bin,virtualenv 文件夹的路径也是如此。

回答by MortenB

I'm not using virtualenv but pyenv: here is it just to use the real .pyenv path in the shebang and make sure it is in the PATH

我不是在使用 virtualenv 而是 pyenv:这里只是在 shebang 中使用真实的 .pyenv 路径并确保它在 PATH 中

Ex: pyenv activate flask-prod for user mortenb which is running in prod

例如:pyenv 为在 prod 中运行的用户 mortenb 激活 flask-prod

/home/mortenb/.pyenv/versions/flask-prod/bin/python --version
Python 3.6.2

Then to my flask scripts starting in systemd *.service I add the following shebang:

然后在以 systemd *.service 开头的烧瓶脚本中添加以下shebang:

#!/home/mortenb/.pyenv/versions/flask-prod/bin/python3