【问题标题】:Python multiprocessing.Process to use virtualenvPython multiprocessing.Process 使用 virtualenv
【发布时间】:2017-10-27 15:31:22
【问题描述】:

我正在使用 virtualenv 运行一个程序。但是这里生成的 multiprocessing.Process 默认使用系统 python。如何强制它使用 virtualenv python。

import os
from multiprocessing import Process

def function1():
    # do_something_here
    p = Process(func2(), args=(param,))
    p.start()
    return something

def func2(param):
    os.system("which python")

这里打印“/usr/bin/python”。但我需要它来使用 virtualenv python。

【问题讨论】:

  • 你确定父进程使用 virtualenv python 启动?
  • @georgexsh 是的。实际上这些函数是烧瓶应用程序的一部分。
  • 我测试了上述程序的一个固定版本(例如你没有func2()作为进程参数但func2,以及其他一些修复),它确实返回了virtualenv版本。尝试在生成进程之前将os.system("which python") 添加到主程序中,看看那里会发生什么。
  • @georgexsh 我正在使用 sudo 运行它。默认情况下,如果您使用 sudo,那么它将使用系统 python。所以,我使用“sudo venv/bin/python main.py”来运行程序。即使我在这里使用 venv 的 python,它也会为“os.system('which python')”返回“/usr/bin/python”。我不明白这种行为。
  • @Kumaran 请注意您接受的答案,这是不准确的。

标签: python virtualenv python-multiprocessing


【解决方案1】:

有了sudo venv/bin/python,你effectively activated virtualenv直接在virtualenv中使用python可执行文件。

multiprocessing.Process 使用fork() 生成子进程,没有exec(),它使用与父进程完全相同的python 可执行文件。

您可以通过以下方式确认 python 可执行文件正在使用中:

>>> import sys
>>> print(sys.executable)
/Users/georgexsh/workspace/tmp/venv/bin/python
>>> print(sys.exec_prefix)
/Users/georgexsh/workspace/tmp/venv/bin/..

不要使用which 来确定正在运行的python 可执行文件路径。 which,作为 Bash 命令,在 $PATH 的每个元素中搜索包含名为“python”的可执行文件的目录,因为您直接使用 virtualenv 的 python,而不是先运行其 shell 激活脚本,$PATH 无法获取打了virtualenv的补丁后,shell命令which python会输出系统python可执行文件的路径。

其实在python层,$PATH是无关紧要的,打补丁$PATH是为了在Bash层方便,在virtualenv路径中调用python可执行文件只需要输入“python”,而不是输入完整路径,最重要的是调用了哪个 python 可执行文件,而不是如何调用它。

【讨论】:

  • 这是正确的。我尝试过这个。 "sys.executable" 打印 venv 的 python 路径,但 "which python" 打印系统 python。谢谢@georgexsh
【解决方案2】:

你的问题在这里(复制你的评论):

@georgexsh 我正在使用 sudo 运行它。默认情况下,如果您使用 sudo 然后它将使用系统python。所以,我使用了“sudo venv/bin/python main.py”来运行程序。即使我在这里使用的是venv的python 它为“os.system('which python')”返回“/usr/bin/python”。我不 理解这种行为

基本上,您在这里解释的是您的 virtualenv 未激活的情况。

当您激活 virtualenv (. venv/bin/activate) 时,激活脚本将更改您的环境,以便您的 PYTHONPATH 正确,并且首先在虚拟 env 目录中搜索(并找到)Python 可执行文件。这就是 virtualenv 所做的。

通过仅从 virtualenv 目录执行 Python 二进制文件,您的环境并未设置为虚拟环境,因此任何后续对 Python 的调用都使用您的默认路径 - 因为 virtualenv 无法覆盖它。

当您执行 sudo 时,会创建一个新进程/shell,并且它不会继承您的虚拟环境。您也许可以使用 sudo -E 传递环境,但这取决于您的 sudo。应该在每个环境中工作的防弹版本是执行一个 shell,它首先激活 virtualenv,然后执行你的脚本。像这样的:

sudo -- bash  -c ". /home/test/mytest/bin/activate; which python"

这会以 root 身份执行一个 bash shell,然后激活虚拟环境,最后告诉你它使用的是哪个 python。只需使用您的虚拟环境路径修改上述命令,它甚至可能会起作用。

如果您的系统是共享的,请记住,从安全角度来看,让您的普通用户这样做是一件可怕的事情。如果您为普通用户创建一个无密码的 sudo 来执行此操作,则只需稍加调整即可为他们提供 root 访问权限。如果是自己的系统,反正要求知道root密码,也没关系。

【讨论】:

  • PYTHONPATH 在这里无所事事,virtualenv 在这里activeProcess 也使用 virtualenv python,你的其他陈述也明显是错误的......跨度>
  • 作为 cmets 状态,OP 最初可能有 virtualenv 处于活动状态,但随后他使用 sudo 执行 Python 和他的脚本,该脚本将 venv PATH 替换为他或系统的默认值。
  • sudo venv/bin/python 有效通过在 virtualenv 中使用 python 可执行文件激活了 virtualenv。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-01-19
  • 2017-03-09
  • 2020-06-05
  • 2017-12-30
  • 1970-01-01
  • 1970-01-01
  • 2015-04-06
相关资源
最近更新 更多