Is it possible to use functions defined in the shell from python?

我只是一个虾纸丫 提交于 2021-02-05 02:16:21

问题


Example:

#!/bin/bash

function my_test(){
    echo this is a test $1
}

my_test 1

python -c "from subprocess import check_output; print(check_output('my_test 2', shell=True))"

output:

this is a test 1
/bin/sh: my_test: command not found
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/lib/python3.5/subprocess.py", line 629, in check_output
    **kwargs).stdout
  File "/usr/lib/python3.5/subprocess.py", line 711, in run
    output=stdout, stderr=stderr)
subprocess.CalledProcessError: Command 'my_test 2' returned non-zero exit status 127

回答1:


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))"



回答2:


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?




回答3:


You can use the os module.

import os
os.system("anything what you would like to do in the shell")



回答4:


The os module is definitely the easiest way and does not cause much trouble in a shell.



来源:https://stackoverflow.com/questions/34556609/is-it-possible-to-use-functions-defined-in-the-shell-from-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!