É ruim ter meu diretório virtualenv dentro do meu repositório git?

284

Estou pensando em colocar o virtualenv para um aplicativo da web Django que estou criando dentro do meu repositório git para o aplicativo. Parece uma maneira fácil de manter a implantação simples e fácil. Existe alguma razão para eu não fazer isso?

Lyle Pratt
fonte

Respostas:

301

Eu uso pip freezepara obter os pacotes necessários em um requirements.txtarquivo e adicioná-lo ao meu repositório. Tentei pensar em uma maneira de você querer armazenar o virtualenv inteiro, mas não consegui.

RyanBrady
fonte
81
Você pode economizar espaço desnecessário no seu repositório e ainda implantar em um novo servidor em um único comando: virtualenv --no-site-packages --distribute .env && source .env / bin / ativar && pip install -r requirements.txt
RyanBrady
2
Eu estou lhe dando a resposta para esta pergunta, pois provavelmente é a "melhor prática" e você a ofereceu primeiro. Eu definitivamente encontrei alguns dos problemas que todos mencionaram. Estou estimando que me dou outro dia brincando com ele antes de fazer o que vocês sempre sugeriram e usar pip e um arquivo de requisitos. Obrigado pela ajuda!
Lyle Pratt
11
Se você, digamos pip install mysql-python, em uma máquina de 64 bits e alguém com uma máquina de 32 bits tentar usá-la, isso não funcionará. Ele usa um módulo C, como muitos módulos Python, para aumentar o desempenho. Eu imagino que o Windows-> Linux também não funcionaria.
Matt Williamson
7
apenas uma observação: recebemos pouco no passado porque, de alguma forma, as bibliotecas estão ficando indisponíveis no pip (versão muito antiga), forçando uma atualização enquanto o site estava inativo. então ... agora nunca mais vou confiar pip freezenisso para fazer isso. o problema é que, durante a atualização forçada da reimplantação, ninguém paga por isso e pelas atualizações intermediárias (manutenção de "práticas recomendadas") também não.
CONTRATO DIZ QUE ESTOU CERTO
5
Nota sobre o comentário @RayanBrady: As opções --distributee --setuptoolsagora não estão disponíveis. (distribuir, que era um fork de setuptools foi mesclado há muito tempo). --no-site-packagesé obsoleto, agora é o comportamento padrão
JackNova
48

Armazenar o diretório virtualenv dentro do git permitirá, como você observou, implantar o aplicativo inteiro executando apenas um clone do git (além de instalar e configurar o Apache / mod_wsgi). Um problema potencialmente significativo com essa abordagem é que, no Linux, o caminho completo é codificado nos scripts de ativação, django-admin.py, easy_install e pip do venv. Isso significa que seu virtualenv não funcionará inteiramente se você desejar usar um caminho diferente, talvez para executar vários hosts virtuais no mesmo servidor. Acho que o site pode realmente funcionar com os caminhos errados nesses arquivos, mas você terá problemas na próxima vez que tentar executar o pip.

A solução, já fornecida, é armazenar informações suficientes no git para que, durante a implementação, você possa criar a virtualenv e fazer as instalações necessárias do pip. Normalmente, as pessoas correm pip freezepara obter a lista e a armazenam em um arquivo chamado requirements.txt. Pode ser carregado com pip install -r requirements.txt. RyanBrady já mostrou como você pode encadear as instruções de implantação em uma única linha:

# before 15.1.0
virtualenv --no-site-packages --distribute .env &&\
    source .env/bin/activate &&\
    pip install -r requirements.txt

# after deprecation of some arguments in 15.1.0
virtualenv .env && source .env/bin/activate && pip install -r requirements.txt

Pessoalmente, eu apenas os coloquei em um script de shell que executei após executar o clone git ou o git pull.

Armazenar o diretório virtualenv também torna um pouco mais complicado lidar com atualizações de pip, pois você terá que adicionar / remover manualmente e confirmar os arquivos resultantes da atualização. Com um arquivo requirements.txt, basta alterar as linhas apropriadas em requirements.txt e executar novamente pip install -r requirements.txt. Como já observado, isso também reduz o "envio de spam".

David Sickmiller
fonte
4
Observe que --distribute agora está obsoleto (pelo menos em 15.1.0): --distribute DEPRECATED. Retained only for backward compatibility. This option has no effect.
AnthonyC
1
--no-site-packagestambém foi preterido na 15.1.0, pois agora é o padrão.
CJS
35

Eu fazia o mesmo até começar a usar bibliotecas compiladas de maneira diferente, dependendo do ambiente, como PyCrypto. Meu Mac PyCrypto não funcionaria no Cygwin não funcionaria no Ubuntu.

Torna-se um pesadelo absoluto para gerenciar o repositório.

De qualquer maneira, achei mais fácil gerenciar o congelamento do pip e um arquivo de requisitos do que ter tudo no git. Também é mais limpo, pois você evita o envio de spam para milhares de arquivos à medida que essas bibliotecas são atualizadas ...

Tomita, Yuji Tomita
fonte
Hmm. Definitivamente, não terei problemas com coisas sendo compiladas de maneira diferente em ambientes diferentes. Eu acho que provavelmente não vale a pena fazê-lo apenas para evitar o spam de confirmação.
Lyle Pratt
@LylePratt: Penso o contrário: é melhor não incluir virtualenv inteiro no repositório apenas para evitar problemas com ferramentas excelentes como PyCrypto ou PIL.
Tadeck 18/12/12
17

Eu acho que um dos principais problemas que ocorrem é que o virtualenv pode não ser utilizável por outras pessoas. A razão é que ele sempre usa caminhos absolutos. Portanto, se você tiver virtualenv, por exemplo, /home/lyle/myenv/ele assumirá o mesmo para todas as outras pessoas que usam este repositório (ele deve ser exatamente o mesmo caminho absoluto). Você não pode presumir pessoas usando a mesma estrutura de diretórios que você.

A melhor prática é que todos estejam configurando seu próprio ambiente (com ou sem virtualenv) e instalando bibliotecas nele. Isso também torna o código mais utilizável em diferentes plataformas (Linux / Windows / Mac), também porque o virtualenv é instalado diferente em cada uma delas.

Torsten Engelbrecht
fonte
Isso está certo porque é uma má ideia manter uma virtualenv no SCM, mas vale a pena considerar algo como a sugestão do @ RJBrady ou o evento de um script bootstrap.py , pois ter alguns meios de recriar o mesmo ambiente nas máquinas é um necessidade séria ao trabalhar com outras pessoas.
ig0774
Não tenho certeza se o problema que você mencionou seria exatamente um problema na minha situação. Meu aplicativo Django contém um arquivo .wsgi que define onde o virtualenv é relativo à sua localização (2 diretórios acima '../../env'). Então, no meu cenário, o problema do caminho absoluto não deve me afetar negativamente ... certo?
Lyle Pratt
Se você executar seu aplicativo sempre com o WSGI, poderá se safar. Se você usar o servidor de desenvolvimento (via manage.py), terá problemas com certeza.
Torsten Engelbrecht
3

Eu uso o que é basicamente a resposta de David Sickmiller com um pouco mais de automação. Crio um arquivo (não executável) no nível superior do meu projeto, nomeado activatecom o seguinte conteúdo:

[ -n "$BASH_SOURCE" ] \
    || { echo 1>&2 "source (.) this with Bash."; exit 2; }
(
    cd "$(dirname "$BASH_SOURCE")"
    [ -d .build/virtualenv ] || {
        virtualenv .build/virtualenv
        . .build/virtualenv/bin/activate
        pip install -r requirements.txt
    }
)
. "$(dirname "$BASH_SOURCE")/.build/virtualenv/bin/activate"

(Conforme a resposta de David, isso pressupõe que você esteja fazendo um pip freeze > requirements.txtpara manter sua lista de requisitos atualizada.)

O exposto acima dá a ideia geral; o script de ativação real ( documentação ) que eu normalmente uso é um pouco mais sofisticado, oferecendo uma -qopção (silenciosa), usando pythonquando python3não está disponível etc.

Isso pode ser originado de qualquer diretório de trabalho atual e será ativado corretamente, primeiro configurando o ambiente virtual, se necessário. Meu script de teste de nível superior geralmente possui código nessas linhas para que possa ser executado sem que o desenvolvedor precise ativar primeiro:

cd "$(dirname "$0")"
[[ $VIRTUAL_ENV = $(pwd -P) ]] || . ./activate

O fornecimento ./activate, não activate, é importante aqui, porque o último encontrará outro activateno seu caminho antes de encontrar o outro no diretório atual.

cjs
fonte
Amando essa abordagem! Parece muito razoável, obrigado por compartilhar.
Esolitos 20/02/19
Eu tive que mudar a primeira linha para [[ $_ != $0 ]] || { echo 1>&2 "source (.) this script with Bash."; exit 2; }detectar se o roteiro foi sendo executado em oposição a origem
Chris Neve
3

Não é uma boa ideia incluir qualquer componente ou configuração dependente do ambiente em seus repositórios, pois um dos principais aspectos do uso de um repositório é, talvez, compartilhá-lo com outros desenvolvedores. Aqui está como eu configuraria meu ambiente de desenvolvimento em um PC com Windows (por exemplo, Win10).

  1. Abra Pycharm e, na primeira página, escolha o projeto no seu Source Control System (no meu caso, estou usando o github)

  2. No Pycharm, navegue até as configurações e escolha "Project Interpreter" e escolha a opção para adicionar um novo ambiente virtual, você pode chamá-lo de "venv".

  3. Escolha o interpretador python base localizado em C: \ Usuários {usuário} \ AppData \ Local \ Programas \ Python \ Python36 (certifique-se de escolher a versão apropriada do Python com base no que você instalou)

  4. Observe que o Pycharm criará o novo ambiente virtual e copiará binários python e bibliotecas necessárias na sua pasta venv dentro da pasta do projeto.

  5. Deixe o Pycharm concluir sua varredura, pois precisa reconstruir / atualizar o esqueleto do seu projeto

  6. excluir a pasta venv de suas interações git (adicione venv \ ao arquivo .gitignore na pasta do seu projeto)

Bônus: se você deseja que as pessoas instalem facilmente (bem, quase facilmente) todas as bibliotecas de que seu software precisa, você pode usar

pip freeze > requirements.txt

e coloque as instruções no seu git para que as pessoas possam usar o seguinte comando para baixar todas as bibliotecas necessárias de uma só vez.

pip install -r requirements.txt 
William Pourmajidi
fonte
2

Se você souber em quais sistemas operacionais seu aplicativo estará executando, eu criaria uma virtualenv para cada sistema e a incluiria no meu repositório. Então eu faria meu aplicativo detectar em qual sistema ele está sendo executado e usar o virtualenv correspondente.

O sistema pode, por exemplo, ser identificado usando o módulo da plataforma .

De fato, é isso que faço com um aplicativo interno que escrevi e ao qual posso adicionar rapidamente um novo virtualv do sistema, caso seja necessário. Dessa forma, não preciso confiar que o pip será capaz de baixar com êxito o software que meu aplicativo exige. Também não precisarei me preocupar com a compilação de, por exemplo, psycopg2, que eu uso.

Se você não souber em qual sistema operacional seu aplicativo pode ser executado, provavelmente será melhor usar o pip freezeque é sugerido em outras respostas aqui.

fredrik
fonte
0

Acho que o melhor é instalar o ambiente virtual em um caminho dentro da pasta do repositório, talvez seja melhor incluir um subdiretório dedicado ao ambiente (excluí acidentalmente todo o meu projeto ao forçar a instalação de um ambiente virtual na raiz do repositório pasta, bom que eu tenha o projeto salvo em sua versão mais recente no Github).

O instalador automatizado ou a documentação devem indicar o caminho virtualenv como um caminho relativo, desta forma você não terá problemas ao compartilhar o projeto com outras pessoas. Sobre os pacotes, os pacotes usados ​​devem ser salvos por pip freeze -r requirements.txt.

Lucioric2000
fonte
-1

Se você acabou de configurar o ambiente de desenvolvimento, use o arquivo pip freeze, caz que limpa o repositório git.

Então, se estiver implementando a produção, verifique a pasta venv inteira. Isso tornará sua implantação mais reproduzível, não precisará desses pacotes libxxx-dev e evitará problemas de Internet.

Portanto, existem dois repositórios. Um para o seu código-fonte principal, que inclui um requirements.txt. E um repositório env, que contém toda a pasta venv.

Shuo
fonte