我正在尝试将列表中的每个项目的需求自动安装到自己的virtualenv中。我已经达到了正确制作virtualenv的程度,但是我无法将它激活并安装到仅仅那个virtualenv:
#!/usr/bin/env python
import subprocess, sys, time, os
HOMEPATH = os.path.expanduser('~')
CWD = os.getcwd()
d = {'cwd': ''}
if len(sys.argv) == 2:
projects = sys.argv[1:]
def call_sp(command, **arg_list):
p = subprocess.Popen(command, shell=True, **arg_list)
p.communicate()
def my_makedirs(path):
if not path.startswith('/home/cchilders'):
path = os.path.join(HOMEPATH, path)
try: os.makedirs(path)
except: pass
for project in projects:
path = os.path.join(CWD, project)
my_makedirs(path)
git_string = 'git clone git@bitbucket.org:codyc54321/{}.git {}'.format(project, d['cwd'])
call_sp(git_string)
d = {'executable': 'bash'}
call_sp("""source /usr/local/bin/virtualenvwrapper.sh && mkvirtualenv --no-site-packages {}""".format(project), **d)
# call_sp("""source /usr/local/bin/virtualenvwrapper.sh && workon {}""".format(project), **d)
# below, the dot (.) means the same as 'source'. the dot doesn't error, calling source does
call_sp('. /home/cchilders/.virtualenvs/{}/bin/activate'.format(project))
d = {'cwd': path}
call_sp("pip install -r requirements.txt", **d)
最终可以
call_sp("""source /usr/local/bin/virtualenvwrapper.sh && mkvirtualenv --no-site-packages {}""".format(project), **d)
但是当脚本结束时,我在venv中没有活动,并且venv没有任何来自要求的包。采购venv(注释和生存的)的两种努力都失败了。
帮助我让mkvirtualenv工作的答案是subprocess.Popen: mkvirtualenv not found。
我还注意到我需要做的不仅仅是pip install,在一种情况下我需要运行'python setup.py mycommand'来自动化每个项目的设置。如何运行命令就像激活virtualenv一样,并且还可以在python脚本中为任意venv安装依赖项?
我找到的唯一方法就是手动启动virtualenv,然后手动调用我的python脚本。我很惊讶,通过bash工作打开它,但调用python脚本被轰炸(可能是因为它与bash不同的过程)
谢谢
答案 0 :(得分:1)
这是因为每个call_sp调用都会创建一个新的shell,因此在第一次调用call_sp之后,所有由virtualenvwrapper的源代码创建的设置都将消失。您必须将所有命令组合到单个call_sp链中。否则你可以使用'Popen'启动shell并使用通信向它发送命令。
如果您使用后者,则需要注意同步和检测何时安装需求结束。 Pip可能需要很长时间才能下载和安装具有复杂依赖关系的包。
答案 1 :(得分:1)
这是我为虚拟环境完成这种引导的方式。让脚本处理它自己的环境并运行脚本。如果缺少,运行这个 app.py 将设置它的 VE 和模块。
./requirements.txt 文件
flask
./app.py 脚本
#!/bin/bash
""":"
VENV=$(realpath -s $(dirname $0)/ve)
PYTHON=$VENV/bin/python
if [ ! -f "$PYTHON" ]; then
echo "installing env app"
python3 -m venv $VENV
${VENV}/bin/pip install -r $(dirname $0)/requirements.txt
fi
exec $PYTHON $0 $@
"""
import flask
print("I am Python with flask", flask)
无论我们在哪个目录中,app.py 都会通过 bash 脚本头进行引导,如果 python 不存在,则安装 ve,运行 pip,以及您需要的任何其他内容。然后 exec $PYTHON $0 $@
是一种将 bash 进程替换为 python 进程保持相同 pid 的巧妙方法。
当 python 接管时,它会跳过 bash 部分,因为该脚本位于三引号字符串中。所以python执行的第一行是import flask
(它丢弃了bash脚本字符串1st)。另一个很酷的事情是 bash 进程的 pid 与 python 进程的 pid 相同。因此,任何照顾它的守护程序实用程序仍将看到它启动的 pid。
最后一个技巧是 bash 需要一个额外的引号来平衡其顶部的字符串 """:"
。 Python 不关心那个额外的引用
我希望你能看到这个模式。要升级 requirements.txt 中的模块,只需 rm ve 并再次运行应用程序。简单。