我使用的是Win 10下的Msys2便携版,但我想这同样适用于许多其他Linuxes/bashes。
如何拥有python脚本,当从shell提示符运行时,了解它的shell函数和相应的参数?
我有一个bash,其中定义了一个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运行时工作得很好。现在,我想在myscript.py中添加行,以便在其中执行myfun,并让它也使用(与以前一样)。
$ python3 myscript.py
编辑#1:在收到答案后,我用export -f myfun导出函数。然后,我在脚本中尝试了6种替代方案:(使用/不使用bash -c),与(subprocess.run、os.system、os.popen)相结合。
我在这里列出了6个组合中的每一个,添加到myscript.py中的行,以及执行python3 myscript.py时获得的输出
import subprocess
subprocess.run(["myfun", "d"])已获得(与以前相同)
Traceback (most recent call last):
...
FileNotFoundError: [Errno 2] No such file or directory: 'myfun'import os
os.system("myfun d")取得了预期的结果。
import os
stream = os.popen("myfun d")获得没有错误,但显然什么都不做(非常奇怪,必须进一步检查发生了什么)。
import subprocess
subprocess.run(["bash", "-c", "myfun", "d"])已获得:执行函数,但忽略函数参数。
import os
os.system("bash -c \"myfun d\"")取得了预期的结果。
import os
stream = os.popen("bash -c \"myfun d\"")获得没有错误,但显然什么都不做(非常奇怪,必须进一步检查发生了什么)。
组织问题与状态
我尝试了几个选项,都失败了(见下面的详细信息)。一方面,即使从bash执行myscript.py,它也会在不了解我的shell函数的情况下启动一个单独的sh shell。另一方面,如果将print( os.environ )添加到myscript.py中,我会看到在~/.bashrc中设置的环境变量,因此至少脚本从shell中正确继承了这些变量。
我在这里列出了添加到myscript.py中的行,以及执行python3 myscript.py时获得的输出
import subprocess
subprocess.run(["myfun", "d"])得奖
Traceback (most recent call last):
...
FileNotFoundError: [Errno 2] No such file or directory: 'myfun'import os
os.system("myfun d")得奖
sh: myfun: command not foundimport os
stream = os.popen("myfun d")得奖
/bin/sh: myfun: command not found发布于 2020-04-26 13:14:27
默认情况下,环境是私有的。导出函数并确保在系统调用中运行bash。myfun是一个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 $*=dhttps://stackoverflow.com/questions/61441379
复制相似问题