Is it possible to use functions defined in the shell from python?
You need to export the shell function, so it will be inherited by child shells.
#!/bin/bash
function my_test(){
echo this is a test $1
}
my_test 1
export -f my_test
python -c "from subprocess import check_output; print(check_output('my_test 2', shell=True))"
Exporting a function, which is not supported by all shells, places the code into the environment block. This is a language-neutral block of text, which is copied from parent to child when a new process is created.
This was the basis of ShellShock.
The trouble is that the two languages Bash and Python are totally different, so a function written in one will not be directly executable by the other without translation. The child process could scan the environment block looking for the function, then translate and compile it into its own language. A lot of work, and could easily be a security issue.
If you just want to go Bash->Python->Bash, then exporting the function from first Bash script should do it, because it will be copied into each environment block. However you also state in a comment that you don't want the first script to export it.
Well you could read the function code using python into a text string, then put it into the environment block yourself (this is what export
does in the shell). Use the os.environ
dictionary.
The actual name used is dependant on your version of Bash. The ShellShock vulnerability resulted in a lot of changes. Best create a test function, export it, then use env
to find its full name. For example on my version a simple function called gash
appears in the environment block as BASH_FUNC_gash%%
.
BASH_FUNC_gash%%=() { echo 'Hollow world'
}
For example:
import os
import subprocess
fun_body="""() { echo 'Hollow world'
}
"""
os.environ['BASH_FUNC_gash%%'] = fun_body
p1 = subprocess.Popen('./myscript.sh')
p1.wait()
The script (myscript.sh
) contains:
#!/bin/bash
gash
Alternatively you could look at your design again. Mixing languages is always problematic, why not write the whole lot in Python?