virtualenvwrapper functions unavailable in shell scripts
Asked Answered
N

8

64

So, once again, I make a nice python program which makes my life ever the more easier and saves a lot of time. Ofcourse, this involves a virtualenv, made with the mkvirtualenv function of virtualenvwrapper. The project has a requirements.txt file with a few required libraries (requests too :D) and the program won't run without these libraries.

I am trying to add a bin/run-app executable shell script which would be in my path (symlink actually). Now, inside this script, I need to switch to the virtualenv before I can run this program. So I put this in

#!/bin/bash
# cd into the project directory
workon "$(cat .venv)"
python main.py

A file .venv contains the virtualenv name. But when I run this script, I get workon: command not found error.

Of course, I have the virtualenvwrapper.sh sourced in my bashrc but it doesn't seem to be available in this shell script.

So, how can I access those virtualenvwrapper functions here? Or am I doing this the wrong way? How do you launch your python tools, each of which has its own virtualenv!?

Nalepka answered 24/9, 2011 at 11:6 Comment(0)
J
81

Just source the virtualenvwrapper.sh script in your script to import the virtualenvwrapper's functions. You should then be able to use the workon function in your script.

And maybe better, you could create a shell script (you could name it venv-run.sh for example) to run any Python script into a given virtualenv, and place it in /usr/bin, /usr/local/bin, or any directory which is in your PATH.

Such a script could look like this:

#!/bin/sh
# if virtualenvwrapper.sh is in your PATH (i.e. installed with pip)
source `which virtualenvwrapper.sh`
#source /path/to/virtualenvwrapper.sh # if it's not in your PATH
workon $1
python $2
deactivate

And could be used simply like venv-run.sh my_virtualenv /path/to/script.py

Jimjams answered 24/9, 2011 at 13:53 Comment(10)
This requires hard-coding the virtualenvwrapper.sh scripts's location, which is dependent on the OS, among many other things.Nalepka
@ShrikantSharat well, as this is meant to be just an easier way for you to run scripts in a virtualenv (so only on your system), it shouldn't really be a problem, is it? If you wanted to distribute your code, i doubt you'd ask users to install virtualenv and create one, you'd simply give him a list of dependencies to install.Jimjams
The users would be my techy friends who would also want a virtualenv for this program's dependencies. I don't have to ask them to ;)Nalepka
@ShrikantSharat hard-coding the path wouldn't be necessary if virtualenvwrapper.sh is in your PATH, which occurs for example when it's installed with pip (I updated my answer accordingly)Jimjams
@MatToufoutu There's an assumption in there, unfortunately. Some systems install virtualenvwrapper being extra "clever": placing it in /etc/bash_completion.d/virtualenvwrapper, which is neither on the path nor named exactly the same thing :( Forces you to symlink it somewhere on such systems.Petard
Why is source `which virtualenvwrapper.sh` wrapped in the "`"?Knockwurst
@Knockwurst to evaluate which virtualenvwrapper.sh and get the script's path (as said, this works only if the script is in the $PATH)Jimjams
@MatToufoutu thanks - what happens if you don't include the ``? In my console it closes the connection somehow...Knockwurst
Is which virtualenvwrapper.sh wrapped in single quotes or grave accents?Overnice
@Overnice it is wrapped in grave-accents/backquotesJimjams
B
9

I can't find the way to trigger the commands of virtualenvwrapper in shell. But this trick can help: assume your env. name is myenv, then put following lines at the beginning of scripts:

ENV=myenv
source $WORKON_HOME/$ENV/bin/activate
Baudoin answered 3/8, 2012 at 8:56 Comment(0)
C
2

This is a super old thread and I had a similar issue. I started digging for a simpler solution out of curiousity.

gnome-terminal --working-directory='/home/exact/path/here' --tab --title="API" -- bash -ci "workon aaapi && python manage.py runserver 8001; exec bash;"

The --workingdirectory forces the tab to open there by default under the hood and the -ci forces it to work like an interactive interface, which gets around the issues with the venvwrapper not functioning as expected.

You can run as many of these in sequence. It will open tabs, give them an alias, and run the script you want.

Personally I dropped an alias into my bashrc to just do this when I type startdev in my terminal.

I like this because its easy, simple to replicate, flexible, and doesn't require any fiddling with variables and whatnot.

Chung answered 17/1, 2020 at 20:39 Comment(0)
R
1

It's a known issue. As a workaround, you can make the content of the script a function and place it in either ~/.bashrc or ~/.profile

function run-app() {
  workon "$(cat .venv)"
  python main.py
} 
Rabies answered 9/6, 2015 at 11:40 Comment(0)
W
0

If your Python script requires a particular virtualenv then put/install it in virtualenv's bin directory. If you need access to that script outside of the environment then you could make a symlink.

main.py from virtualenv's bin:

#!/path/to/virtualenv/bin/python
import yourmodule

if __name__=="__main__":
   yourmodule.main()

Symlink in your PATH:

pymain -> /path/to/virtualenv/bin/main.py

In bin/run-app:

#!/bin/sh
# cd into the project directory
pymain arg1 arg2 ...
Wilson answered 24/9, 2011 at 12:31 Comment(4)
This works, but I don't like putting the path to virtualenv's python in the #! line, feels a bit dirty. Also, this extra step of creating the main.py inside the virtualenv makes it less portable. My friends can't just clone and run it from me :)Nalepka
@Shrikant Sharat: If you write simple setup.py then pip install does for you both shebang and copying to virtualenv/bin. Your friends can just: pip install git+... if they like bleeding edge. Note in this case main.py is copied to their virtualenv and shebang is written to point to their virtualenv/python.Wilson
@Sebastian, Never considered that option but it sounds good. Any good doc reading on that you recommend (other than the python docs which I am checking out now), if any. Thanks!Nalepka
@Shrikant Sharat: e.g., guide.python-distribute.org pip-installer.orgWilson
N
0

Apparently, I was doing this the wrong way. Instead of saving the virtualenv's name in the .venv file, I should be putting the virtualenv's directory path.

(cdvirtualenv && pwd) > .venv

and in the bin/run-app, I put

source "$(cat .venv)/bin/activate"
python main.py

And yay!

Nalepka answered 24/9, 2011 at 14:20 Comment(0)
A
0

add these lines to your .bashrc or .bash_profile

export WORKON_HOME=~/Envs
source /usr/local/bin/virtualenvwrapper.sh

and reopen your terminal and try

Ablative answered 2/7, 2013 at 11:11 Comment(0)
L
0

You can also call the virtualenv's python executable directly. First find the path to the executable:

$ workon myenv
$ which python
/path/to/virtualenv/myenv/bin/python

Then call from your shell script:

#!/bin/bash

/path/to/virtualenv/myenv/bin/python myscript.py
Lactometer answered 17/8, 2013 at 16:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.