I am trying to write what should be a super simple bash script. Basically activate a virtual env and than change to the working directory. A task i do a lot and condesing to one command just made sense.
Basically ...
#!/bin/bash
source /usr/local/turbogears/pps_beta/bin/activate
cd /usr/local/turbogears/pps_beta/src
However when it runs it just dumps back to the shell and i am still in the directory i ran the script from and the environment isn't activated.
All you need to do is to run your script with the source command. This is because the cd command is local to the shell that runs it. When you run a script directly, a new shell is executed which terminates when it reaches the script's end of file. By using the source command you tell the shell to directly execute the script's instructions.
The value of cd is local to the current script, which ends when you fall off the end of the file.
What you are trying to do is not "super simple" because you want to override this behavior.
Look at exec for replacing the current process with the process of your choice.
For feeding commands into an interactive Bash, look at the --rcfile option.
I imagine you wish your script to be dynamic, however, as a quick fix when working on a new system I create an alias.
begin i.e
the env is called 'py1' located at ~/envs/py1/ with a repository
location at ~/proj/py1/
alias py1='source ~/envs/py1/bin/activate; cd ~/proj/py1/;
end i.e
You can now access your project and virtualenv by typing py1 from anywhere in the CLI.
I know that this is no where near ideal, violates DRY, and many other programming concepts. It is just a quick and dirty way of getting your env and project accessible quickly without having to setup the variables.
I know that I'm late to the game here, but may I suggest using virtualenvwrapper? It provides a nice bash hook that appears to do exactly what you want.
Check out this tutorial: http://blog.fruiapps.com/2012/06/An-introductory-tutorial-to-python-virtualenv-and-virtualenvwrapper
Related
I want to a up a cron job to run a python script each day within a virtual environment. So I've tried to set up a cron job but it does not seem to execute.
If I were to run the program from terminal normally, I would type:
source ig/venv/bin/activat enter to activate my virtual environment
cd ig/mybot/src/ navigate to my directory
python ultimate.py run my program
SO FAR this is my cron job. I've set it to 1 to run every minute just so I can see that it is working but nothing happens.
1 * * * * source ig/venv/bin/activate && cd ig/mybot/src/ && python ultimate.py
Edit: I have updated my program so no command line prompts are required. I am just needing to run these three simple commands.
You can wrap this up with another python script itself. Create a new python script and run it instead of cron.
Have a look into subprocess module.
Example:
Your command would become subprocess.call(['source','ig/venv/bin/activate'])
inside the wrapper python script.
Also, input("Enter the value") will prompt you for user input.
With the above two, your problem will be solved pythonically.
I'm not sure if it's a good idea, but you could do a script like this.
#!/usr/bin/env bash
PYTHON_PROJECT_DIR=/path/to/python/project/dir
pushd ${PYTHON_PROJECT_DIR}
VALUES="first line of stream\nsecondline of stream\n"
pipenv run /path/to/your/script.py < (echo -e $VALUES)
popd
pushd and popd are commands to move with the directory stack, so you'll be in the directory in the top of the stack, so by adding one directory, you move to the working directory, and by poping you'll get back to the initial position.
Using pipenv allows you to run the scripts in the virtual enviroment (It's not that hard to configure), that way you'll use the enviroment variables in the .env files for the project, and you'll only use the dependencies of this project. (python related).
If you pass the values like this, the python script when ever it requests a value from stdin it will use the values that you echoed (line by line, first line is first input and so on)
This could be a way.
Personally when ever I do cronjobs I like to run directly bash scripts, because, I could add extra logging, so having the wrapper script doesn't seem that unreasonable.
Another thing you could do, Is to get the python executable path (for the virtual enviroment), and use that as interpreter, by replacing the #!/usr/bin/env python to #!/path/to/pythons/virtual/env/interpreter
but you won't get the .env variables (may be there is a way to actually get them.
Background:
I'm using Windows. I know some of programming with python. I don't know much about batch, which I think I might need to do what I want.
I will show a example so it becomes more clear what I'm trying to do.
Example:
When using git, after you install it, you can call the git command from anywhere of your computer, you can execute git commands, like git init and this will create a git file in your current folder.
I don't know exactly how git works or what language they use but I want to do the same thing, create my own command that I can execute from anywhere in my computer after I "install" my program.
What I'm trying to do:
I want to make my own command and when I call it, it executes a python script.
e.g.
I install my program and it creates a command called myprogram and when I type myprogram in the command line, it's like if I typed python myprogram.py. And myprogram -someargument would be the same as python myprogram.py -someargument.
What I tried until now:
I'm searched for How to make a environment variable that runs Python script? but I never get exactly what I want, is always something like How do I set environment variable using Python script?.
Maybe I'm making the wrong question and the result I want are not showing?
I'm looking for a explanation on how to do this or at least a tutorial/guide.
Edit 1:
As UnholySheep said in the comments, it's not environment variable, its commands, so I changed the question even does what I want to know is the same thing.
Files you need:
First you need a python script (obviously) so I created a file called myprogram.py that have this simple line:
print("This should be from a command")
After you need to make a batch file, in my case I used a .cmd file called myprogram.cmd that have:
#ECHO OFF
python_directory\python.exe python_script_directory\myprogram.py %*
Configurations to make:
You need to set in PATH environment variable the location of the batch file batch_file_directory\myprogram.cmd
And now if you execute in the command line myprogram it will print This should be from a command.
You can also use .exe or .bat files.
To start off, I am a complete noob to Debian, Python, and shell scripts, so please speak to me like I am a toddler.
I have a python script I am running through a virtualenv, and I want to execute it via a shell script. Here is what I'm typing in to the terminal to do so:
source .profile
workon cv
cd Desktop/Camera
python main.py
I tried turning this into a shell script, but I receive the error -- source: not found
I've found no answer to my problem, at least not in any terms I can understand. Any advice would be appreciated. Furthermore, before you answer, I also have no idea why it is I need to execute source .profile, I'm simply following a beginner guide for the project which can be found here: https://www.hackster.io/hackerhouse/smart-security-camera-90d7bd
Thanks in advance, and sorry if this is a dumb question.
Best practice for Shell would be shebang at the begging like #Veda suggested.
Execute the shell script using bash like bash shell.sh as the link suggests using relative locations rather than absolute ones
Add a hashbang at the top of your script (should be the first line):
#!/bin/bash
This will ensure you are running your shell-script in bash. Having a shell does not mean it's bash. Not all shells have the source function that you are using (bash has it).
Some prefer the following:
#!/usr/bin/env bash
Since you are a "beginner" I think it does not really matter. The first makes sure it's using the bash in /bin, the second is using the PATH variable to find bash, so the user of your script can provide it's own bash if he/she wants.
I'm trying to change the terminal directory through a python script. I've seen this post and others like it so I know about os.chdir, but it's not working the way I'd like. os.chdir appears to change the directory, but only for the python script. For instance I have this code.
#! /usr/bin/env python
import os
os.chdir("/home/chekid/work2/")
print os.getcwd()
Unfortunately after running I'm still in the directory of the python script (e.g. /home/chekid) rather than the directory I want to be in. See below.
gandalf(pts/42):~> pwd
/home/chekid
gandalf(pts/42):~> ./changedirectory.py
/home/chekid/work2
gandalf(pts/42):~> pwd
/home/chekid
Any thoughts on what I should do?
Edit: Looks like what I'm trying to do doesn't exist in 'normal' python. I did find a work around, although it doesn't look so elegant to me.
cd `./changedirectory.py`
You can't. The shell's current directory belongs to the shell, not to you.
(OK, you could ptrace(2) the shell and make it call chdir(2), but that's probably not a great design, won't work on Windows, and I would not begin to know how to do it in pure Python except that you'd probably have to mess around with ctypes or something similar.)
You could launch a subshell with your current working directory. That might be close enough to what you need:
os.chdir('/path/to/somewhere')
shell = os.environ.get('SHELL', '/bin/sh')
os.execl(shell, shell)
# execl() does not return; it replaces the Python process with a new shell process
The original shell will still be there, so make sure you don't leave it hanging around. If you initially call Python with the exec builtin (e.g. exec python /path/to/script.py), then the original shell will be replaced with the Python process and you won't have to worry about this. But if Python exits without launching the shell, you'll be left with no shell open at all.
You can if you cheat: Make a bash script that calls your python script. The python script returns the path you want to change directory to. Then the bash script does the acctual chdir. Of course you would have to run the bash script in your bash shell using "source".
The current working directory is an attribute of a process. It cannot be changed by another program, such as changing the current working directory in your shell by running a separate Python program. This is why cd is always a shell built-in command.
You can make your python print the directory you want to move to, and then call your script with cd "$(./python-script.py)". In condition your script actually does not print anything else.
I find that when I start the python shell I have a bunch of commands I always type to get into the state I want. It is tiresome to keep re-typing these commands, so I have bundled them into a script. Now I just type:
execfile('script.py')
as soon as I enter the shell, and it goes through all the steps to get me to the state I need to be in.
Now I'd like to take it one step further. How can I get the python shell to automatically run script.py every time I start the shell, so I don't have to keep re-typing even that one line?
Here's a way without having to mess with environment variables:
For example, if I had a script with the following in it called script.py:
#!/usr/bin/env python
print("example")
I could tell python to run this before bringing me to the interpreter with the -i flag.
$ python -i script.py
example
>>>
I think you're looking for the PYTHONSTARTUP environment variable
I'd suggest you to use IPython, if possible. It gives tones of great features, and autoexec is only one of them. But of course, correct answer is mentioned by #mgilston
Create a file called usercustomize.py, and place it in your USER_SITE directory (which you can find as import site; site._script(). This file will be executed every time you start an interpreter.
There's a similar file called sitecustomize.py which is executed anytime anyone starts Python.
This is a Windows solution, but I'm sure a Unix equivalent could be done. I created a file \MyPythonCode\autoexec.py (the last line of which is a print("Autoexec Complete")) and a BAT file MyPython.Bat which has:
cd \myPythonCode
python -i autoexec.py
I just use the command: mypython
to start the Python environment every time, now.