Skip to content

Instantly share code, notes, and snippets.

@welbornprod
Created August 14, 2014 23:22
Show Gist options
  • Star 24 You must be signed in to star a gist
  • Fork 7 You must be signed in to fork a gist
  • Save welbornprod/ccbf43393ecd610032f4 to your computer and use it in GitHub Desktop.
Save welbornprod/ccbf43393ecd610032f4 to your computer and use it in GitHub Desktop.
A little trick to embed python code in a BASH script.
#!/bin/bash
# Here are some embedded Python examples using Python3.
# They are put into functions for separation and clarity.
# Simple usage, only using python to print the date.
# This is not really a good example, because the `date`
# command works just as well.
function date_time {
python3 - <<END
from datetime import datetime
print('Current date:')
print(datetime.now())
END
}
# Call the python code.
date_time
# Sending a variable to Python from BASH
function env_args {
# Put an environment arg into Python.
# Must be on the same line as the command.
TESTARG="My Value" python3 - <<END
from os import environ
print('Your environment arg: {}'.format(environ.get('TESTARG', 'missing!')))
END
}
env_args
# Retrieve output from Python and put it into a BASH variable.
# This uses a subshell to retrieve whatever python prints out.
function val_from_python {
# Get a python value from BASH.
pythonval="$(python3 - <<END
import os
print('cwd: {}'.format(os.getcwd()))
END
)"
echo "Python value is: $pythonval"
}
val_from_python
# You can put small python snippets directly into your shell files.
# Here's an example using `urllib` to download some html, and then
# using it in BASH.
# (granted that you could do this in Python itself,
# or you could write it all in BASH, but this is just an example.)
function python_power {
# Grab the html from python.org's PEP8 page and save it to a bash variable.
# On error, the output will be a basic HTML page with the error message.
local pythonval="$(python3 - <<END
from urllib import request
try:
resp = request.urlopen('http://legacy.python.org/dev/peps/pep-0008/')
data = resp.read().decode('utf-8')
print(data)
except Exception as ex:
print("""
<html>\n<head>\n<title>Error in python_power</title>\n</head>\n
<body>\nThere was an error retrieving that page: {}\n</body>
""".format(ex))
END
)"
# Print the content so it can be used by other commands.
# (you also could've saved it to a global variable.)
echo $pythonval
}
# Direct the output of this python function to a file.
# The html will not be styled correctly, because no css files are downloaded.
# But the point here is that you can have the full power of python without
# writing separate scripts. Small python snippets can be embedded and used
# from BASH itself.
outfile='pep8.html'
python_power > $outfile
if [[ -f $outfile ]]; then
echo "New file was created: $outfile"
google-chrome $outfile
else
echo "Unable to create new file: $outfile"
fi
@tobiashochguertel
Copy link

Here is a example to make embedded python code working which needs a tty / pty, because it interacts with the user:

I wanted to have a sexy ui in my shell scripts, and found the python library bullet and wrapped it into my bash scripts like above described, but bullet needs a tty / pty an with here documents there is no tty / pty available. I found the following StackOverflow post and combined everything together.

#!/bin/bash

# Name: bselect()
# Arg: selection-items
# Example:
#    bselect "root $USER $username"
#
# Example:
#    Call it and capture the output
#
#    SELECTION=$(bselect "root $USER $username")
#    echo "Selected User": $SELECTION
#
bselect(){
    read -r -d '' script <<-"----EOF"
			import os
			from bullet import Bullet
			selections = os.environ['PYTHON_ARG'].split()
			print(selections)

			cli = Bullet(
			        prompt = "\nPlease choose: ",
			        choices = selections,
			        return_index = True
			    )

			result = cli.launch()
			print(result)
----EOF
PYTHON_ARG="$1" python -c "$script"
}

Example bash call:

bselect "root $USER $username"

Preview:

image

@tobiashochguertel
Copy link

Okay updated Code, had some issues with getting it working with return value capturing, and do a workaround - which isn't a nice way when you have two processes using bselect at the same time... but I can facilitate with that for the moment.

# Name: bselect()
# Arg: selection-items
# Example:
#    bselect "root $USER $username"
#
# Example: (wished I get it working to be like this example...)
#    Call it and capture the output
#
#    SELECTION=$(bselect "root $USER $username")
#    echo "Selected User": $SELECTION
#
#
# Example: (working example, workaround with writing the selection result to a file, and in bash script to cat the file)
#    Call it and capture the output
#
#    	bselect "root $USER $username"
#   	username=$(cat ~/.bselect)
#     echo "Selected User": $username
#
bselect(){
    read -r -d '' script <<-"----EOF"
			import os
			import json
			from bullet import Bullet
			selections = os.environ['PYTHON_ARG'].split()
			print(selections)

			cli = Bullet(
			        prompt = "\nPlease choose: ",
			        choices = selections,
			        return_index = False
			    )

			result = cli.launch()
			# print("export PYTHON_RETURN=%s" % result)
			# print(result)
			f = open(os.path.expanduser('~/.bselect'), 'w')
			f.write(result)
			f.close()
----EOF
PYTHON_ARG="$1" python -c "$script"
}

Example bash call:

   	bselect "root $USER $username"
   	username=$(cat ~/.bselect)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment