Cara mengaktifkan sumber virtualenv dalam skrip Bash


106

Bagaimana Anda membuat skrip Bash untuk mengaktifkan virtualenv Python?

Saya memiliki struktur direktori seperti:

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

Saya dapat mengaktifkan virtualenv saya dengan:

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

Namun, melakukan hal yang sama dari skrip Bash tidak melakukan apa-apa:

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

Apa yang saya lakukan salah?


6
Saat Anda menjalankan skrip shell, Anda sebenarnya membuat shell baru. Tujuan penggunaannya sourceadalah untuk mengubah sesuatu di shell saat ini. Anda dapat menggunakan python virtualenv menggunakan jalur lengkap ./env/bin/python.
Pablo Navarro

@NgureNyaga, Tidak, pertanyaan itu tidak sama dengan pertanyaan saya. Mereka bertanya bagaimana cara mendapatkan sumber dari lokasi yang sewenang-wenang. Saya sudah tahu bagaimana melakukan ini. Saya bertanya bagaimana cara membuat sumber dalam skrip bash kustom dan mempertahankan sumbernya.
Cerin

Jawaban:


84

Saat Anda membuat sumber, Anda memuat skrip pengaktifan ke dalam shell aktif Anda.

Saat Anda melakukannya dalam skrip, Anda memuatnya ke shell yang keluar saat skrip Anda selesai dan Anda kembali ke shell asli yang belum diaktifkan.

Pilihan terbaik Anda adalah melakukannya dalam sebuah fungsi

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

atau alias

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

Semoga ini membantu.


untuk windows c: \ tutorial>. \ env \ Scripts \ aktifkan
max4ever

7
Saya sama sekali tidak tahu apa yang terjadi ketika saya melakukan source. Ini telah sangat mengubah skrip bash saya menjadi lebih baik. Terima kasih!
Robert Townley

1
Ide alias Anda bekerja dengan baik untuk saya juga. Sekadar catatan: Saya harus meletakkannya (alias abcdef = "source ... / bin / activation") di skrip .zshrc saya (atau .bashrc untuk pengguna bash) agar bisa berfungsi.
Syahins

Ini adalah solusi yang bagus jika virtualenv Anda menggunakan nama folder default. Saya dulu memiliki lebih dari satu repo di folder, membuat kekacauan di virtualenvs. Saya beralih ke default ini sekarang.
3manuek

3
Saya baru mengenal bash dll. Dapatkah Anda memperluas contoh ini sehingga menampilkan skrip lengkap?
AljoSt

60

Anda harus memanggil skrip bash menggunakan source.

Berikut ini contohnya:

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

Di cangkang Anda, sebut saja seperti itu:

> source venv.sh

Atau seperti yang disarankan @outmind: (Perhatikan bahwa ini tidak berfungsi dengan zsh)

> . venv.sh

Ini dia, indikasi shell akan ditempatkan pada prompt Anda.


2
atau bahkan hanya ". venv.sh"
melebihi

tidak peduli apa yang saya coba, ini source "/home/surest/Desktop/testservers/TEST_VENV/venv3/bin/activate"menghasilkan:/home/surest/Desktop/testservers/TEST_VENV/py3.sh: 10: /home/surest/Desktop/testservers/TEST_VENV/py3.sh: source: not found

Saya juga tidak mendapatkan apa-apa ketika saya mengetik which sourcedi prompt shell, namun, source venv3/bin/activatemelakukan apa yang saya harapkan dan membuka venv. ...

Mengapa ini berhasil, tetapi source ./env/bin/activate(dengan #!/bin/bashawalan yang sama ) tidak? Apa perbedaan antara menggunakan kutipan dan tidak?
gelap

Saya tidak punya masalah menggunakan sumber di dalam skrip tanpa tanda kutip. Saya melihat masalah source ./env/bin/activatekarena ini relatif terhadap jalur yang Anda jalankan, bukan? Jika Anda mengubah direktori di dalam skrip daripada Anda bisa menjadi relatif.
Flavio Garcia

14

Meskipun tidak menambahkan awalan "(.env)" ke prompt shell, saya menemukan skrip ini berfungsi seperti yang diharapkan.

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

misalnya

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
secara teknis Anda menelurkan subkulit. Ini belum tentu menjadi masalah, tetapi Anda harus menjelaskannya untuk OP.
richo

Ini berhasil, tetapi saya harus memberikan izin ke file "aktifkan" saya sebelumnya.
Adrian Lopez

1
Ini berfungsi di 2019! Di macOS, saya hanya perlu mengubah /bin/bashke/usr/bin/env bash
valem

Berfungsi di Ubuntu 18.04 AWS EC2 pada tahun 2020. Saya ingin tahu bagaimana cara menonaktifkannya menggunakan logika yang sama?
CSF Junior

Anda deactivatedari subkulit dengan exitatau Ctrl + d
Alexx Roche

10

Sourcing menjalankan perintah shell di shell Anda saat ini. Saat Anda mengambil sumber di dalam skrip seperti yang Anda lakukan di atas, Anda memengaruhi lingkungan untuk skrip itu, tetapi saat skrip keluar, perubahan lingkungan dibatalkan, karena secara efektif berada di luar cakupan.

Jika maksud Anda adalah menjalankan perintah shell di virtualenv, Anda bisa melakukannya di skrip Anda setelah mencari sumber skrip pengaktifan. Jika Anda bermaksud untuk berinteraksi dengan shell di dalam virtualenv, maka Anda bisa menelurkan sub-shell di dalam skrip Anda yang akan mewarisi lingkungan.


3

Berikut script yang sering saya gunakan. Jalankan sebagai$ source script_name

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

activate

2

Untuk apa sumber skrip bash?

  1. Jika Anda berniat untuk beralih di antara beberapa virtualenv atau memasuki satu virtualenv dengan cepat, sudahkah Anda mencobanya virtualenvwrapper? Ini menyediakan banyak kegunaan seperti workon venv, mkvirtualenv venvdan sebagainya.

  2. Jika Anda hanya menjalankan skrip python di virtualenv tertentu, gunakan /path/to/venv/bin/python script.pyuntuk menjalankannya.


Sebenarnya, saya ingin menelepon workon ...dari skrip bash. (Karena saya ingin mengeksekusi hal-hal lebih lanjut setelahnya setiap kali saat startupnya.) Namun, tidak dapat menemukan cara untuk membuatnya berfungsi.
Daniel B.10

1

Anda juga dapat melakukan ini menggunakan subkulit untuk lebih menampung penggunaan Anda - berikut adalah contoh praktisnya:

#!/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"

Gaya ini sangat membantu saat

  • versi lain dari commandAatau commandCada di bawah/opt/bin
  • commandBada dalam sistem PATHatau sangat umum
  • perintah ini gagal di bawah virtualenv
  • seseorang membutuhkan berbagai virtualenv yang berbeda

Jangan lupa untuk memberi tanda kutip ganda $(...)atau Anda akan kehilangan spasi dan tab yang terdapat dalam output.
Eric

"${VAR}"sama persis dengan "$VAR"Anda tidak perlu tanda kurung kurawal di sekitar variabel shell karena tanda kutip ganda sebenarnya lebih efektif. Pengecualiannya adalah saat menggunakan pengubah seperti misalnya"${VAR:-default_value}"
Eric

PATH=$PATH:/opt/binmembutuhkan kutipan yang tepat untuk menangani jalur dengan spasi dan tab.
Eric

@Eric Terima kasih, meskipun Anda dapat menggunakan edittombol di bawah posting untuk menyarankan perubahan kepada mereka! Lebih lanjut, perlu diketahui bahwa meskipun sering kali merupakan persyaratan dan penting untuk keselamatan, siapa pun yang dengan sengaja menambahkan IFSkarakter PATHadalah teroris.
ti7

0

Anda harus menggunakan banyak perintah dalam satu baris. sebagai contoh:

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

ketika Anda mengaktifkan lingkungan virtual Anda dalam satu baris, saya pikir itu melupakan baris perintah lain dan Anda dapat mencegahnya dengan menggunakan beberapa perintah dalam satu baris. Itu berhasil untuk saya :)


0

Ketika saya masih belajar venv saya membuat script untuk mengingatkan saya bagaimana mengaktifkannya.

#!/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

Ini memiliki keuntungan karena mengubah prompt.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.