python - Python使用shell函数
问题描述
我在 Win 10 下使用 Msys2 便携版,但我想这同样适用于许多其他 Linux/bash。
从 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.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\"")
获得 没有错误,但显然什么也没做(很奇怪,必须进一步检查发生了什么)。
原始问题和状态:
我尝试了几个选项,都失败了(请参阅下面的详细信息)。一方面,似乎即使myscript.py
从 bash shell执行,它也会在sh
不知道我的 shell 函数的情况下启动一个单独的 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 found
- 添加
import os
stream = os.popen("myfun d")
获得
/bin/sh: myfun: command not found
解决方案
默认情况下,环境是私有的。导出函数并确保它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 $*=d
推荐阅读
- cordova - 使用 Cordova 脚本创建 .ipa 文件
- umbraco - Umbraco 7.4 URL 重定向功能
- typescript - X 类型的参数不能分配给 Y 类型的参数(尽管有继承)
- regex - 结构替换可能复杂的 RegexReplace 解决方案?
- r - 使用 lme4 自定义引导置信区间
- sql-server - SQL Server 中的正则表达式 - 连字符分隔的字符串
- javascript - javascript 将函数对象传递给网络工作者 - 无法克隆错误 DataCloneError
- swift - 如何在 swiftUI 中添加拖动手势以便更改视图?有点像 Snapchat,向右滑动可以让你看到故事?
- javascript - 将日期添加到数组的 Javascript for 循环会冻结某些 PC 上的页面
- c# - 尝试运行 Web 应用程序时出现 System.InvalidOperationException