วิธีการเปิดใช้งาน Virtualenv ในสคริปต์ Bash


106

คุณสร้างสคริปต์ Bash เพื่อเปิดใช้งาน Python Virtualenv ได้อย่างไร?

ฉันมีโครงสร้างไดเรกทอรีเช่น:

.env
    bin
        activate
        ...other virtualenv files...
src
    shell.sh
    ...my code...

ฉันสามารถเปิดใช้งาน Virtualenv ของฉันได้โดย:

user@localhost:src$ . ../.env/bin/activate
(.env)user@localhost:src$

อย่างไรก็ตามการทำสิ่งเดียวกันจากสคริปต์ Bash ไม่ได้ทำอะไรเลย:

user@localhost:src$ cat shell.sh
#!/bin/bash
. ../.env/bin/activate
user@localhost:src$ ./shell.sh
user@localhost:src$ 

ผมทำอะไรผิดหรือเปล่า?


6
เมื่อคุณรันเชลล์สคริปต์คุณกำลังสร้างเชลล์ใหม่ จุดที่ใช้sourceคือการเปลี่ยนบางสิ่งในเชลล์ปัจจุบัน คุณสามารถใช้หลาม virtualenv ./env/bin/pythonโดยใช้เส้นทางแบบเต็ม
Pablo Navarro

@NgureNyaga ไม่คำถามนั้นไม่เหมือนกับของฉัน พวกเขากำลังถามถึงวิธีการหาแหล่งที่มาจากสถานที่โดยพลการ ฉันรู้แล้วว่าต้องทำอย่างไร ฉันกำลังถามวิธีการหาแหล่งที่มาภายในสคริปต์ทุบตีที่กำหนดเองและรักษาแหล่งที่มา
Cerin

คำตอบ:


84

เมื่อคุณต้นทางคุณกำลังโหลดสคริปต์เปิดใช้งานลงในเชลล์ที่ใช้งานอยู่

เมื่อคุณทำในสคริปต์คุณจะโหลดลงในเชลล์ซึ่งจะออกเมื่อสคริปต์ของคุณเสร็จสิ้นและคุณจะกลับไปที่เชลล์ดั้งเดิมที่ไม่ได้เปิดใช้งาน

ตัวเลือกที่ดีที่สุดของคุณคือทำในฟังก์ชัน

activate () {
  . ../.env/bin/activate
}

หรือนามแฝง

alias activate=". ../.env/bin/activate"

หวังว่านี่จะช่วยได้


สำหรับ windows c: \ tutorial>. \ env \ Scripts \
enable

7
ฉันไม่รู้เลยว่านั่นคือสิ่งที่เกิดขึ้นเมื่อฉันหาแหล่งข้อมูลสิ่งนี้ได้เปลี่ยนสคริปต์ทุบตีของฉันให้ดีขึ้น ขอบคุณ!
Robert Townley

1
แนวคิดนามแฝงของคุณก็ใช้ได้ดีสำหรับฉันเช่นกัน หมายเหตุ: ฉันต้องใส่ (alias abcdef = "source ... / bin / enable") ในสคริปต์. zshrc ของฉัน (หรือ. bashrc สำหรับผู้ใช้ bash) เพื่อให้มันใช้งานได้
shahins

นี่เป็นทางออกที่ดีหากคุณมีคุณธรรมโดยใช้ชื่อโฟลเดอร์เริ่มต้น ฉันเคยมี repo มากกว่าหนึ่งโฟลเดอร์ในโฟลเดอร์ทำให้ยุ่งกับ Virtualenvs ฉันเปลี่ยนมาใช้ค่าเริ่มต้นนี้แล้ว
3 มนูญ

3
ฉันค่อนข้างใหม่กับการทุบตี ฯลฯ คุณสามารถขยายตัวอย่างนี้เพื่อให้แสดงสคริปต์ทั้งหมดได้หรือไม่
AljoSt

60

คุณควรเรียกสคริปต์ทุบตีโดยใช้แหล่งที่มา

นี่คือตัวอย่าง:

#!/bin/bash
# Let's call this script venv.sh
source "<absolute_path_recommended_here>/.env/bin/activate"

บนเปลือกของคุณเพียงแค่เรียกมันว่า:

> source venv.sh

หรือตามที่ @outmind แนะนำ: (โปรดทราบว่าสิ่งนี้ใช้ไม่ได้กับ zsh)

> . venv.sh

เอาล่ะตัวบ่งชี้เชลล์จะถูกวางไว้บนพรอมต์ของคุณ


2
หรือแม้แต่ ". venv.sh"
เหนือกว่า

ไม่ว่าฉันจะพยายามอย่างไรสิ่งนี้source "/home/surest/Desktop/testservers/TEST_VENV/venv3/bin/activate"ก่อให้เกิด:/home/surest/Desktop/testservers/TEST_VENV/py3.sh: 10: /home/surest/Desktop/testservers/TEST_VENV/py3.sh: source: not found

ฉันยังไม่ได้รับอะไรเลยเมื่อฉันพิมพ์which sourceที่เชลล์พรอมต์ แต่source venv3/bin/activateก็ทำในสิ่งที่ฉันคาดหวังและเปิด venv ...

เหตุใดจึงใช้งานได้ แต่source ./env/bin/activate(มี#!/bin/bashคำนำหน้าเหมือนกัน) ไม่ได้? การใช้เครื่องหมายคำพูดกับไม่แตกต่างกันอย่างไร
blacksite

ฉันไม่มีปัญหาในการใช้แหล่งที่มาภายในสคริปต์โดยไม่มีเครื่องหมายคำพูด ฉันพบปัญหาsource ./env/bin/activateเพราะนี่สัมพันธ์กับเส้นทางที่คุณกำลังวิ่งใช่ไหม หากคุณเปลี่ยนไดเร็กทอรีภายในสคริปต์เกินกว่าที่คุณจะสามารถเชื่อมโยงได้
Flavio Garcia

14

แม้ว่าจะไม่ได้เพิ่มคำนำหน้า "(.env)" ในเชลล์พรอมต์ แต่ฉันพบว่าสคริปต์นี้ทำงานได้ตามที่คาดไว้

#!/bin/bash
script_dir=`dirname $0`
cd $script_dir
/bin/bash -c ". ../.env/bin/activate; exec /bin/bash -i"

เช่น

user@localhost:~/src$ which pip
/usr/local/bin/pip
user@localhost:~/src$ which python
/usr/bin/python
user@localhost:~/src$ ./shell
user@localhost:~/src$ which pip
~/.env/bin/pip
user@localhost:~/src$ which python
~/.env/bin/python
user@localhost:~/src$ exit
exit

5
ในทางเทคนิคแล้วคุณกำลังวางไข่ย่อย ไม่จำเป็นต้องเป็นปัญหา แต่คุณควรสะกดคำนั้นสำหรับ OP
richo

มันใช้งานได้ แต่ฉันต้องให้สิทธิ์ไฟล์ "เปิดใช้งาน" ก่อน
Adrian Lopez

1
ใช้งานได้ในปี 2019! บน MacOS ฉันเพิ่งมีการเปลี่ยน/bin/bashไป/usr/bin/env bash
VALEM

ใช้งานได้ใน Ubuntu 18.04 AWS EC2 ในปี 2020 ฉันสงสัยว่าจะปิดใช้งานโดยใช้ตรรกะเดียวกันได้อย่างไร?
CSF Junior

คุณdeactivateจาก subshell ด้วยexitหรือ Ctrl + d
Alexx Roche

10

Sourcing รันคำสั่งเชลล์ในเชลล์ปัจจุบันของคุณ เมื่อคุณซอร์สโค้ดภายในสคริปต์เช่นเดียวกับที่คุณกำลังทำข้างต้นคุณกำลังส่งผลกระทบต่อสภาพแวดล้อมของสคริปต์นั้น แต่เมื่อสคริปต์ออกการเปลี่ยนแปลงสภาพแวดล้อมจะถูกยกเลิกเนื่องจากสิ่งเหล่านี้อยู่นอกขอบเขตอย่างมีประสิทธิภาพ

หากเจตนาของคุณคือเรียกใช้คำสั่งเชลล์ใน Virtualenv คุณสามารถทำได้ในสคริปต์ของคุณหลังจากจัดหาสคริปต์เปิดใช้งาน หากเจตนาของคุณคือการโต้ตอบกับเชลล์ภายใน Virtualenv คุณสามารถสร้างเชลล์ย่อยภายในสคริปต์ของคุณซึ่งจะสืบทอดสภาพแวดล้อม


3

นี่คือสคริปต์ที่ฉันใช้บ่อย เรียกใช้เป็น$ source script_name

#!/bin/bash -x
PWD=`pwd`
/usr/local/bin/virtualenv --python=python3 venv
echo $PWD
activate () {
    . $PWD/venv/bin/activate
}

activate

2

การจัดหาสคริปต์ทุบตีเพื่ออะไร

  1. หากคุณตั้งใจจะสลับไปมาระหว่าง Virtualenv หลายตัวหรือเข้าสู่ Virtualenv อย่างรวดเร็วคุณได้ลองvirtualenvwrapperหรือยัง? มันให้มาก utils เหมือนworkon venv, mkvirtualenv venvและอื่น ๆ

  2. หากคุณเพิ่งเรียกใช้สคริปต์ python ใน Virtualenv บางตัวให้ใช้/path/to/venv/bin/python script.pyเพื่อเรียกใช้


ที่จริงฉันอยากจะเรียกworkon ...จากสคริปต์ทุบตี (เพราะฉันต้องการดำเนินการเพิ่มเติมหลังจากนั้นทุกครั้งที่เริ่มต้น) ไม่สามารถหาวิธีที่จะทำให้มันใช้งานได้
Daniel B.

1

คุณยังสามารถทำได้โดยใช้ subshell เพื่อให้มีการใช้งานของคุณได้ดีขึ้นนี่คือตัวอย่างที่ใช้ได้จริง:

#!/bin/bash

commandA --args

# Run commandB in a subshell and collect its output in $VAR
# NOTE
#  - PATH is only modified as an example
#  - output beyond a single value may not be captured without quoting
#  - it is important to discard (or separate) virtualenv activation stdout
#    if the stdout of commandB is to be captured
#
VAR=$(
    PATH="/opt/bin/foo:$PATH"
    . /path/to/activate > /dev/null  # activate virtualenv
    commandB  # tool from /opt/bin/ which requires virtualenv
)

# Use the output from commandB later
commandC "$VAR"

สไตล์นี้มีประโยชน์อย่างยิ่งเมื่อ

  • เวอร์ชันอื่นcommandAหรือcommandCมีอยู่ภายใต้/opt/bin
  • commandBมีอยู่ในระบบPATHหรือเป็นเรื่องธรรมดามาก
  • คำสั่งเหล่านี้ล้มเหลวภายใต้ Virtualenv
  • เราต้องการคุณธรรมที่แตกต่างหลากหลาย

อย่าลืมอ้างสองครั้งมิ$(...)ฉะนั้นคุณจะไม่มีช่องว่างและแท็บที่อยู่ในผลลัพธ์
Eric

"${VAR}"เทียบเท่ากับ"$VAR"คุณไม่จำเป็นต้องมีวงเล็บปีกการอบตัวแปรเชลล์เนื่องจากอัญประกาศคู่มีพลังมากกว่า ข้อยกเว้นคือเมื่อใช้ตัวปรับแต่งเช่น"${VAR:-default_value}"
Eric

PATH=$PATH:/opt/binต้องการคำพูดที่เหมาะสมเพื่อจัดการกับเส้นทางที่มีช่องว่างและแท็บ
Eric

@Eric ขอบคุณแม้ว่าคุณจะสามารถใช้editปุ่มด้านล่างโพสต์เพื่อแนะนำการเปลี่ยนแปลงได้! นอกจากนี้โปรดทราบว่าแม้ว่ามักจะเป็นข้อกำหนดและมีความสำคัญต่อความปลอดภัย แต่ใครก็ตามที่เพิ่มIFSตัวอักษรให้PATHเป็นผู้ก่อการร้าย
ti7

0

คุณควรใช้คำสั่งหลายคำสั่งในบรรทัดเดียว ตัวอย่างเช่น:

os.system(". Projects/virenv/bin/activate && python Projects/virenv/django-project/manage.py runserver")

เมื่อคุณเปิดใช้งานสภาพแวดล้อมเสมือนของคุณในหนึ่งบรรทัดฉันคิดว่ามันลืมสำหรับบรรทัดคำสั่งอื่น ๆ และคุณสามารถป้องกันสิ่งนี้ได้โดยใช้หลายคำสั่งในบรรทัดเดียว มันได้ผลสำหรับฉัน :)


0

เมื่อฉันเรียนรู้ Venv ฉันได้สร้างสคริปต์เพื่อเตือนวิธีเปิดใช้งาน

#!/bin/sh
# init_venv.sh
if [ -d "./bin" ];then
  echo "[info] Ctrl+d to deactivate"
  bash -c ". bin/activate; exec /usr/bin/env bash --rcfile <(echo 'PS1=\"(venv)\${PS1}\"') -i"
fi

สิ่งนี้มีข้อดีคือเปลี่ยนพรอมต์

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.