Python 使用 shell 函数



我在 Win 10 下使用 Msys2 可移植,但我想这同样适用于许多其他 Linux/bashe。

当从 shell 提示符运行时,我如何让 python 脚本了解其 shell 函数和相应的参数?

我有一个 bash shell,其中我定义了一个 shell 函数myfun

$ type myfun
myfun is a function
myfun ()
{
...
(this contains a call to a shell script, 
that is found in a directory which is part of $PATH)
}

可以采用参数,例如$ myfun d, 我有一个 python 脚本myscript.py从 bash shell 运行时运行良好。 现在我想向myscript.py添加行以从其中执行myfun,并使其也与(与以前相同)一起工作

$ python3 myscript.py



编辑#1: 收到答案后,我导出了带有export -f myfun的函数。 然后我在脚本中尝试了 6 种替代方案:(使用/不使用bash -c),结合 (subprocess.runos.systemos.popen)。

我在这里列出了 6 种组合中的每一个,添加到myscript.py的行,以及执行python3 myscript.py时获得的输出:

  1. 添加
import subprocess
subprocess.run(["myfun", "d"])

获得(与以前相同)

Traceback (most recent call last):
...
FileNotFoundError: [Errno 2] No such file or directory: 'myfun'
  1. >已添加
import os
os.system("myfun d")

获得了预期的结果。

  1. >已添加
import os
stream = os.popen("myfun d")

获得 没有错误,但显然什么都不做(很奇怪,必须进一步检查发生了什么)。

  1. >已添加
import subprocess
subprocess.run(["bash", "-c", "myfun", "d"])

获得: 执行了函数,但忽略了函数参数。

  1. >已添加
import os
os.system("bash -c "myfun d"")

获得了预期的结果。

  1. 已添加
import os
stream = os.popen("bash -c "myfun d"")

获得 没有错误,但显然什么都不做(很奇怪,必须进一步检查发生了什么)。



原始问题和状态

我尝试了一些选项,但都失败了(请参阅下面的详细信息)。 一方面,似乎即使从 bash shell 执行myscript.py,它也会在不知道我的 shell 函数的情况下启动一个单独的shshell。 另一方面,如果将print( os.environ )添加到myscript.py,我看到在~/.bashrc中设置的环境变量,因此至少脚本从 shell 正确继承了它。


我在这里列出了添加到myscript.py的行,以及执行python3 myscript.py时获得的输出:
  1. 添加
import subprocess
subprocess.run(["myfun", "d"])

获得

Traceback (most recent call last):
...
FileNotFoundError: [Errno 2] No such file or directory: 'myfun'
  1. >已添加
import os
os.system("myfun d")

获得

sh: myfun: command not found
  1. >已添加
import os
stream = os.popen("myfun d")

获得

/bin/sh: myfun: command not found

默认情况下,环境是私有的。导出函数并确保在系统调用中运行bashmyfun是一个bash函数,你必须运行bash才能运行它的函数。

$ myfun() { echo 1; }
$ export -f myfun
$ python <<<'import os; os.system("bash -c myfun")'
1
$ python <<<'import subprocess as s; s.run(["bash", "-c", "myfun"])'
1
$ python <<<'import os; os.popen("bash -c 'myfun"); # ... '

我通常将参数传递给内部 bash 命令作为脚本的参数,并在扩展$@传递正确引用:

$ myfun() { echo "$#=$#" "$*=$*"; }
$ export -f myfun
$ python <<<'import os; os.system("bash -c "myfun \"$@\"" -- d")'
$#=1 $*=d
# or way better use subprocess
$ python <<<'import subprocess as s; s.run(["bash", "-c", "myfun "$@"", "--", "d"])'
$#=1 $*=d
# but still can do the more unsafe version
# that will undergo word expansion or you have to properly escape the strings
# (and double-double escape for `os.systems`)
$ python <<<'import subprocess as s; s.run(["bash", "-c", "myfun d"])'
$#=1 $*=d

最新更新