उपयोगकर्ता के रूप में कपड़े के माध्यम से एक virtualenv सक्रिय करें


130

मैं अपनी फैब्रिक स्क्रिप्ट को स्थानीय रूप से चलाना चाहता हूं, जो बदले में, मेरे सर्वर में लॉग इन करेगा, उपयोगकर्ता को तैनात करने के लिए स्विच करेगा, प्रोजेक्ट्स को सक्रिय करेगा ।virtualenv, जो प्रोजेक्ट के लिए dir को बदल देगा और git पुल जारी करेगा।

def git_pull():
    sudo('su deploy')
    # here i need to switch to the virtualenv
    run('git pull')

मैं आमतौर पर virtualenvwrapper से वर्कऑन कमांड का उपयोग करता हूं, जो सक्रिय फ़ाइल को स्रोत बनाता है और पोस्टएक्टिनेट फ़ाइल मुझे प्रोजेक्ट फ़ोल्डर में डाल देगा। इस मामले में, ऐसा लगता है कि क्योंकि कपड़े खोल के भीतर से चलते हैं, नियंत्रण कपड़े को दे दिया जाता है, इसलिए मैं बैश के स्रोत को '$ स्रोत ~ / .virtualenv / myvenv / बिन / सक्रिय' में उपयोग नहीं कर सकता।

किसी के पास एक उदाहरण और स्पष्टीकरण है कि उन्होंने यह कैसे किया है?


1
जिज्ञासा से बाहर, आप workonएक के रूप में उपयोग क्यों नहीं कर रहे हैं prefix?
डैनियल सी। सोबराल

जवाबों:


96

अभी, आप वही कर सकते हैं जो मैं करता हूं, जो कि kludgy है, लेकिन पूरी तरह से अच्छी तरह से काम करता है * (यह उपयोग आप virtualenvwrapper का उपयोग कर रहे हैं - जो आपको होना चाहिए - लेकिन आप आसानी से लंबे समय तक 'स्रोत' कॉल में स्थानापन्न कर सकते हैं, जिसका आपने उल्लेख किया है , अगर नहीं):

def task():
    workon = 'workon myvenv && '
    run(workon + 'git pull')
    run(workon + 'do other stuff, etc')

संस्करण 1.0 के बाद से, फैब्रिक का एक prefixसंदर्भ प्रबंधक है जो इस तकनीक का उपयोग करता है ताकि आप उदाहरण के लिए:

def task():
    with prefix('workon myvenv'):
        run('git pull')
        run('do other stuff, etc')

* ऐसे मामले होने की संभावना है जहां command1 && command2दृष्टिकोण का उपयोग करने से आप पर झटका लग सकता है, जैसे कि जब command1विफल हो ( command2कभी नहीं चलेगा) या यदि command1ठीक से बच नहीं गया है और इसमें विशेष शेल वर्ण हैं, और इसके आगे।


7
लेकिन workonद्वारा अज्ञात है sh। हम कपड़े को बश का उपयोग करने के लिए कैसे कह सकते हैं?
पियरे डे लेसपिन

18
IMHO आपको बस उपयोग करना चाहिए source venv/bin/activate। यह आसान है और बॉक्स से बाहर काम करता है। workonएक अतिरिक्त निर्भरता है और यहां तक ​​कि अगर यह स्थापित है तो आपको इसे जोड़ना होगा .bashrc- कपड़े के लिए बहुत जटिल।
डेव हाल्टर

@PierredeLESPINAY आपकी समस्या के समाधान के लिए stackoverflow.com/questions/11272372/… देखें ।
डूकबॉडी

137

बिटप्रॉपेट के पूर्वानुमान के अद्यतन के रूप में: फैब्रिक 1.0 के साथ आप उपसर्ग () और अपने स्वयं के संदर्भ प्रबंधकों का उपयोग कर सकते हैं ।

from __future__ import with_statement
from fabric.api import *
from contextlib import contextmanager as _contextmanager

env.hosts = ['servername']
env.user = 'deploy'
env.keyfile = ['$HOME/.ssh/deploy_rsa']
env.directory = '/path/to/virtualenvs/project'
env.activate = 'source /path/to/virtualenvs/project/bin/activate'

@_contextmanager
def virtualenv():
    with cd(env.directory):
        with prefix(env.activate):
            yield

def deploy():
    with virtualenv():
        run('pip freeze')

@simon, अपने स्वयं के उपसर्ग विधि को लिखकर जो .bashrc बुलाता है और bash के लिए -c तर्क के भीतर उपसर्ग और कमांड दोनों को लपेटता है। नीचे
डेव

5
लेकिन sourceद्वारा अज्ञात है sh। हम कपड़े को बश का उपयोग करने के लिए कैसे कह सकते हैं?
पियरे डी लेसपिन

2
@PierredeLESPINAY के .बदले आप उपयोग कर सकते हैंsource
katy lavallee

क्यों प्रयोग करते हैं cd()जब आप पूरी तरह से करने के लिए पथ निर्दिष्ट कर रहे हैं activateमें prefix()?
निक टी

@NickT क्योंकि prefix()वहाँ सीडी नहीं लगती है - इन डॉक्स को देखें जो ऐसा ही करते हैं। हम cdवहां जाना चाहते हैं ताकि जब हम yieldअन्य कमांड्स ( pip freezeमेरे उदाहरण में) निष्पादित करें , तो वे कमांड उस निर्देशिका के सापेक्ष हो सकते हैं।
nh2

18

मैं बस एक साधारण आवरण फ़ंक्शन virtualenv () का उपयोग कर रहा हूं जिसे रन () के बजाय कहा जा सकता है। यह सीडी संदर्भ प्रबंधक का उपयोग नहीं करता है, इसलिए रिश्तेदार पथ का उपयोग किया जा सकता है।

def virtualenv(command):
    """
    Run a command in the virtualenv. This prefixes the command with the source
    command.
    Usage:
        virtualenv('pip install django')
    """
    source = 'source %(project_directory)s/bin/activate && ' % env
    run(source + command)

9

virtualenvwrapper इसे थोड़ा सरल बना सकते हैं

  1. @ NH2 के दृष्टिकोण का उपयोग करना (का उपयोग करते समय इस दृष्टिकोण भी काम करता है local, लेकिन केवल प्रतिष्ठानों जहां virtualenvwrapper के लिए workonमें है $PATH, दूसरे शब्दों में - विंडोज)

    from contextlib import contextmanager
    from fabric.api import prefix
    
    @contextmanager
    def virtualenv():
        with prefix("workon env1"):
            yield
    
    def deploy():
        with virtualenv():
            run("pip freeze > requirements.txt")
  2. या अपनी फैब फ़ाइल को तैनात करें और इसे स्थानीय रूप से चलाएं। यह सेटअप आपको स्थानीय या दूरस्थ कमांड के लिए virtualenv को सक्रिय करने देता है। यह दृष्टिकोण शक्तिशाली है, क्योंकि यह चारों ओर से काम करता है local's का उपयोग करके .bashrc चलाने के लिए असमर्थता bash -l:

    @contextmanager
    def local_prefix(shell, prefix):
        def local_call(command):
            return local("%(sh)s \"%(pre)s && %(cmd)s\"" % 
                {"sh": shell, "pre": prefix, "cmd": command})
        yield local_prefix
    
    def write_requirements(shell="/bin/bash -lic", env="env1"):
        with local_prefix(shell, "workon %s" % env) as local:
            local("pip freeze > requirements.txt")
    
    write_requirements()  # locally
    run("fab write_requirements")

Nh2 के उत्तर को सारांशित करने के लिए धन्यवाद, वर्चुअन रेफ़रमैनेजर घोषणा पाइथन 2.6+ पर 5 लाइनों में की जा सकती है, हालांकि यह कभी गारंटी नहीं है कि 'वर्कऑन' उपनाम हमेशा सही तरीके से आयात किया जाता है, और यह इस स्रोत का उपयोग करने के लिए अधिक विश्वसनीय है ... / सक्रिय करें ' कमान
एलेक्स वोल्कोव

8

यह virtualenvस्थानीय तैनाती के साथ उपयोग करने के लिए मेरा दृष्टिकोण है ।

फैब्रिक के पथ () संदर्भ प्रबंधक का उपयोग करके आप virtualenv से बायनेरिज़ के साथ चला सकते हैं pipया कर सकते हैं python

from fabric.api import lcd, local, path

project_dir = '/www/my_project/sms/'
env_bin_dir = project_dir + '../env/bin/'

def deploy():
    with lcd(project_dir):
        local('git pull origin')
        local('git checkout -f')
        with path(env_bin_dir, behavior='prepend'):
            local('pip freeze')
            local('pip install -r requirements/staging.txt')
            local('./manage.py migrate') # Django related

            # Note: previous line is the same as:
            local('python manage.py migrate')

            # Using next line, you can make sure that python 
            # from virtualenv directory is used:
            local('which python')

मुझे यह बहुत पसंद है - मुझे इस दृष्टिकोण के लिए कोई स्पष्ट नुकसान नहीं दिखता है, और यह बहुत साफ है। धन्यवाद :)
सिमोन

अभी भी सबसे अच्छा और सबसे साफ जवाब यहां
n1_

4

पोस्ट किए गए सभी उत्तरों के लिए धन्यवाद और मैं इसके लिए एक और विकल्प जोड़ना चाहूंगा। एक मॉड्यूल, फैब्रिक-वर्चुनेल है , जो फ़ंक्शन को समान कोड प्रदान कर सकता है:

>>> from fabvenv import virtualenv
>>> with virtualenv('/home/me/venv/'):
...     run('python foo')

कपड़े- virtualenv का उपयोग करता है fabric.context_managers.prefix, जो एक अच्छा तरीका हो सकता है :)


दिलचस्प है, लेकिन मुझे यह तथ्य पसंद नहीं है कि SCM / इश्यू ट्रैकर का लिंक नहीं है। एक पैकेज जो केवल स्रोत कोड के लिंक के बिना PYPI पर प्रकाशित होता है और ट्रैकर जारी करता है, बहुत विश्वास को प्रेरित नहीं करता है .... लेकिन इसे ठीक करना आसान है।
18:18

2

यदि आप संकुल को पर्यावरण में स्थापित करना चाहते हैं या पर्यावरण में आपके द्वारा संकुल के अनुसार कमांड चलाना चाहते हैं, तो मैंने अपनी समस्या को हल करने के लिए, कपड़े के जटिल तरीकों को लिखने या नए OS पैकेजों को स्थापित करने के बजाय यह हैक पाया है:

/path/to/virtualenv/bin/python manage.py migrate/runserver/makemigrations  # for running commands under virtualenv

local("/home/user/env/bin/python manage.py migrate")    # fabric command


/path/to/virtualenv/bin/pip install -r requirements.txt   # installing/upgrading virtualenv

local("/home/user/env/bin/pip install -r requirements.txt")  #  fabric command

इस तरह से आपको पर्यावरण को सक्रिय करने की आवश्यकता नहीं हो सकती है, लेकिन आप पर्यावरण के तहत कमांड निष्पादित कर सकते हैं।


1

यहां एक डेकोरेटर के लिए कोड है जो किसी भी रन / सुडोल कॉल के लिए वर्चुअल एनवायरनमेंट का उपयोग करेगा।

# This is the bash code to update the $PATH as activate does
UPDATE_PYTHON_PATH = r'PATH="{}:$PATH"'.format(VIRTUAL_ENV_BIN_DIR)

def with_venv(func, *args, **kwargs):
  "Use Virtual Environment for the command"

  def wrapped(*args, **kwargs):
    with prefix(UPDATE_PYTHON_PATH):
      return func(*args, **kwargs)

  wrapped.__name__ = func.__name__
  wrapped.__doc__ = func.__doc__
  return wrapped

और फिर डेकोरेटर का उपयोग करने के लिए, ध्यान दें कि डेकोरेटर का क्रम महत्वपूर्ण है:

@task
@with_venv
def which_python():
  "Gets which python is being used"
  run("which python")

1

यह दृष्टिकोण मेरे लिए काम करता है, आप इसे भी लागू कर सकते हैं।

from fabric.api import run 
# ... other code...
def install_pip_requirements():
    run("/bin/bash -l -c 'source venv/bin/activate' "
        "&& pip install -r requirements.txt "
        "&& /bin/bash -l -c 'deactivate'")

मान लें venvकि आपकी वर्चुअल एनवी डायरेक्टरी है और जहाँ भी उपयुक्त हो, इस विधि को जोड़ें।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.