Executing Python Scripts
(poorly written, revise)
which Interpreter?
This simple program shows how many days remain until a future date.
Simply add this script to ~/bin
(or another folder in your path) and make it executable.
#!/Users/fy/anaconda3/bin/python
# daysleft: a program to show how many days are left until a future date
import datetime
# input
event='The Exam'
future_date=datetime.date(2019,3,28)
#
today=datetime.date.today()
days_left=future_date-today
print(f'Today is {today}')
print(f'{days_left.days} days are left until {event} on {future_date}')
Note: The first line is the output of
azizcodes$ which python
/Users/fy/anaconda3/bin/python
Executing,
azizcodes$ daysleft
Today is 2019-03-18
10 days are left until The Exam on 2019-03-28
which is shorter than writing python script.py
each time.
A More Flexible Way
A more flexible way of specifying the interpreter is using #!/usr/bin/env python
. From Stackoverflow
#!/usr/bin/python is hardcoded to always run /usr/bin/python, while #!/usr/bin/env python will run whichever python would be default in your current environment (it will take in account for example $PATH, you can check which python interpreter will be used with which python). The second way ( #!/usr/bin/env python ) is preferred , as it’s not dependent on particular installation. It will work for example with virtualenv setups or systems where there is no /usr/bin/python, but only e.g. /usr/local/bin/python.
Calling Python from with Bash
Here is an example. Call this file python_from_bash
.
#!/bin/bash
python_code(){
cat << EOF
# script.py
import datetime
event='The Exam'
future_date=datetime.date(2019,3,28)
today=datetime.date.today()
days_left=future_date-today
print(f'Today is {today}')
print(f'{days_left.days} days are left until {event} on {future_date}')
EOF
}
python -c "$(python_code)"
Now run
azizcodes$ python_from_bash
and it should execute. This has the advantage of having a whole program contained in one file, if that’s what you want. Ofcourse, you can run the following just as easily
#!/bin/bash
python script.py
Speaking of Executing Strings..
bash -c string
This command executes string
. This opens the possibility of getting a string through curl
and executing it on the fly, such is done by Homebrew (with Ruby, though, but same idea)
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
which can be an easy and transparent way of installing scripts. Unfortunately, as famous Homebrew is, I haven’t seen people use this trick. But I am gonna change that, because it’s too elegant!
A Start-Up Script
Here is a small project: I have my preferences saved in my .bash_profile
but I have many devices. It would be nice if I can have one folder of user scripts synchronized across all of them. By downloading a git file (and pulling the updated version, if it is already there) and then copying the scripts to the ~/bin/
folder and making them executable.
All in one command:
bash -c "$(curl -fsSL https://raw.githubusercontent.com/azizcodes/myscripts/master/download)"
which executes this script.
This command will do the following
- Download the following files to
~/projects/myscripts
(or update that folder if it exists, through agit pull
) - README
bin_info
, run this command to show usage instructionsadd_profile
, run this command to copy the.bash_profile
bashprofile
, for your reference, a list of shell functiondownload
, for your reference, the script to downloadmyscripts
- Copies the scripts to
~/bin
- Make them executable
Workflow
- To upload, make changes and push them to the shared repository from the device
- To download, just execute the above command
PS: I know I can just simply clone ~/bin
from a git repository and keep it synchronized, which is probably a lot easier. But I wanted to test and illustrate this method.