سؤال

أريد تشغيل البرنامج النصي من النسيج الخاص بي محليا، والتي ستنقل إلى الخادم الخاص بي، قم بتسجيل الدخول إلى المستخدم للنشر، قم بتنشيط المشاريع .virtualenv، والتي ستغير DIR إلى المشروع وإصدار سحب GIT.

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

عادة ما استخدم الأمر Workon من VirtualenvWrapper الذي يصدر مصادر ملف التنشيط ويقوم بوضع ملف PostActivate في مجلد المشروع. في هذه الحالة، يبدو أنه نظرا لأن النسيج يعمل من داخل SHELT، فإن السيطرة تستسلم للنسيج، لذلك لا يمكنني استخدام مصدر باش المدمج إلى "مصدر $ المصدر ~ / .virtualenv / myvenv / bin / تنشيط"

أي شخص لديه مثال وتفسير كيف فعلوا هذا؟

هل كانت مفيدة؟

المحلول

الآن، يمكنك أن تفعل ما أقوم به، وهو كلودجي ولكنه يعمل بشكل جيد تماما * (يفترض هذا الاستخدام أنك تستخدم 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 لم يتم هربه بشكل صحيح ويحتوي على شخصيات قذيفة خاصة، وما إلى ذلك.

نصائح أخرى

كتحديث لتوقعات bitprophet: مع النسيج 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')

أنا فقط باستخدام وظيفة غلاف بسيطة Virtualenv () التي يمكن استدعاؤها بدلا من التشغيل (). لا يستخدم مدير سياق CD، حتى يمكن استخدام المسارات النسبية.

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)

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. أو نشر ملف Fab الخاص بك وتشغيل هذا محليا. يتيح لك هذا الإعداد تنشيط VirtualEnv للأوامر المحلية أو البعيدة. هذا النهج قوي لأنه يعمل حولها localعدم القدرة على تشغيل .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")
    

هذا هو نهجي في استخدام virtualenv مع عمليات النشر المحلية.

باستخدام النسيج طريق() مدير السياق يمكنك تشغيله pip أو python مع الثنائيات من virtualenv.

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')

شكرا لجميع الإجابات المنشورة وأود أن أضيف بديل واحد آخر لهذا. هناك وحدة نمطية، النسيج - virtualenv., ، والتي يمكن أن توفر الوظيفة بنفس الرمز:

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

النسيج - virtualenv يستفيد من fabric.context_managers.prefix, ، والتي قد تكون طريقة جيدة :)

إذا كنت ترغب في تثبيت الحزم على البيئة أو ترغب في تشغيل الأوامر وفقا للحزم التي لديك في البيئة، فقد وجدت أن هذا الاختراق لحل مشكلتي، بدلا من كتابة طرق معقدة من النسيج أو تثبيت حزم 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

وبهذه الطريقة، قد لا تحتاج إلى تنشيط البيئة، ولكن يمكنك تنفيذ الأوامر تحت البيئة.

هنا هو رمز المزخرف الذي سيؤدي إلى استخدام البيئة الافتراضية لأي مكالمات تشغيل / سودو:

# 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")

عمل هذا النهج بالنسبة لي، يمكنك تطبيق هذا أيضا.

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 هو دليل ENV الظاهري وإضافة هذه الطريقة أينما كان ذلك مناسبا.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top