这篇文章主要围绕从Shell脚本调用Python函数和shell脚本调用python脚本展开,旨在为您提供一份详细的参考资料。我们将全面介绍从Shell脚本调用Python函数的优缺点,解答shell
这篇文章主要围绕从Shell脚本调用Python函数和shell脚本调用python脚本展开,旨在为您提供一份详细的参考资料。我们将全面介绍从Shell脚本调用Python函数的优缺点,解答shell脚本调用python脚本的相关问题,同时也会为您带来bash – 如何将stdin从shell脚本重定向到shell脚本中的命令?、bash – 无法从shell脚本调用Openscad -D命令行、bash – 通过sudo – 环境变量从另一个shell脚本调用shell脚本?、go执行python/shell脚本的实用方法。
本文目录一览:- 从Shell脚本调用Python函数(shell脚本调用python脚本)
- bash – 如何将stdin从shell脚本重定向到shell脚本中的命令?
- bash – 无法从shell脚本调用Openscad -D命令行
- bash – 通过sudo – 环境变量从另一个shell脚本调用shell脚本?
- go执行python/shell脚本
从Shell脚本调用Python函数(shell脚本调用python脚本)
我试图弄清楚如何从Shell脚本调用Python函数。
我有一个具有多个功能的Python文件,我需要在我的shell脚本中使用它们返回的值。有没有办法做到这一点。
我这样做是为了使用Python读取配置文件并在shell中获取值。还有其他更好的方法来实现这一目标。
test.py
包含:
import ConfigParserconfig = ConfigParser.ConfigParser()config.read("test.conf")def get_foo(): return config.get("locations", "foo")def get_bar(): return config.get("locations", "bar")
我需要将Python函数返回的值存储在shell变量中。
答案1
小编典典您可以通过要求Python解释器打印结果来将函数的结果发送到标准输出:
python -c ''import test; print test.get_foo()''
该-c
选项只是要求Python执行一些Python命令。
为了将结果存储在变量中,因此可以执行以下操作:
RESULT_FOO=`python -c ''import test; print test.get_foo()''`
或者,等效地
RESULT=$(python -c ''import test; print test.get_foo()'')
自反引号起,并$(…)
评估命令并用其输出替换它。
PS :要获取每个功能的结果,都需要使用这种方法每次都解析配置文件。可以通过一次返回所有结果来优化此过程,例如:
ALL_RESULTS=$(python -c ''import test; print test.get_foo(), test.get_bar()'')
然后可以将结果拆分并放入不同的变量中
RESULT_BAR=$(echo $ALL_RESULTS | cut -d'' '' -f2)
它以 第二个 结果并将其放入RESULT_BAR
(例如,类似地:-fn
对于结果#n)。
PPS :正如Pablo
Maurin提到的那样,如果可能的话,在一个解释器(Python,但也可能在Shell)中完成所有操作可能会更容易,而不是在一个程序中计算变量并在另一个程序中使用它们。
bash – 如何将stdin从shell脚本重定向到shell脚本中的命令?
我想替换
find . -type f | $JAVA_HOME/bin/java com.domain.BatchProcess
同
find . -type f | ./batch.sh
解决方法
$JAVA_HOME/bin/java com.domain.BatchProcess
期待来自stdin的输入,然后将其放入脚本中并运行第二个命令将起作用.
bash – 无法从shell脚本调用Openscad -D命令行
$openscad -o output.stl -D 'param1="name1"' -D 'param2="name2"' openscad-script.scad
编辑:注意我们必须传递-D参数的方式,单引号和双引号必须根据因为Openscad documentation.
但当我生成&从shell脚本执行相同的命令,openscad失败并出现错误:
$./myscript.sh value1 value2
ERROR: Parser error in line XX: Syntax error Can’t parse file
‘openscad-script.scad’!
其中XX =文件的最后一行.
这是bash脚本
#!/bin/bash # run openscad command param1="-D 'param1=\"$1\"'" param2="-D 'param2=\"$2\"'" echo "openscad -o $1-$2.stl $param1 $param2 openscad-script.scad" openscad -o $1-$2.stl $param1 $param2 openscad-script.scad
这看起来很简单,我仍然无法弄清楚opencad在运行命令时失败的原因.
谢谢你的帮助,
编辑:我发现了一种让它工作的方法,可能不是最好的
#!/bin/bash # run openscad command param1="-D 'param1=\"$1\"'" param2="-D 'param2=\"$2\"'" command = "openscad -o $1-$2.stl $param1 $param2 openscad-script.scad" eval $command
解决方法
openscad -o name1-name2.stl -D 'param1="name1"' -D 'param2="name2"' openscad-script.scad
…然后执行此操作的正确脚本将是:
#!/bin/bash openscad \ -o "$1-$2.stl" \ -D "param1=\"$1\"" \ -D "param2=\"$2\"" \ openscad-script.scad
…或者,如果你真的想因为某种原因在多行上建立东西:
#!/bin/bash args=( -o "$1-$2.stl" ) args+=( -D "param1=\"$1\"" ) args+=( -D "param2=\"$2\"" ) openscad "${args[@]}" openscad-script.scad
openscad字面上无法知道命令行中是否使用了单引号或双引号,因此没有可强制执行的方法来要求单引号.而且,shell引用是逐个字符的属性!也就是说:
'param1="name1"' # becomes the C string "param1=\"name1\""
导致完全相同的字符串传递为:
param1='"name1"' # becomes the C string "param1=\"name1\"",same as above
要么
param1='"'name1'"' # becomes the C string "param1=\"name1\"",same as above
……当这些值都是常数时.但是,当name1被替换为$1之类的东西时,根据使用的引号类型,含义会变得非常不同:
set -- name1; IFS=0123456789 "param1=\"$1\"" # becomes the C string "param1=\"name1\"",as above 'param1="$1"' # becomes the C string "param1=\"$1\"",not substituting name1 # ...and,as an example of something to look out for: param1='"'$1'"' # becomes TWO C strings,"param1=\"name" and "\"",due to bad quoting # ...the IFS above makes it split on numbers; by default this risk would happen with spaces
bash – 通过sudo – 环境变量从另一个shell脚本调用shell脚本?
#!/bin/bash # script_A.sh export VAR="value" enter code here sudo -u user ./script_B.sh #!/bin/bash # script_B.sh echo $VAR # this prints nothing
解决方法
为了保护环境,请将-E切换到sudo.
来自sudo手册页:
-E
The
-E
(preserve environment) option indicates to the security policy that the user wishes to preserve their existing
environment variables. The security policy may return an error if the-E
option is specified and the user does not have permission to preserve the environment.
go执行python/shell脚本
一、背景
项目的后台是golang, 但是一个子模块是python写好了的,为了能够快速使用上,打算用golang调用python。但是从长远的角度来看,在服务内部,跨语言,跨进程,最好使用RPC的方式。 本文主要讲解如何通过go来调用python脚本或者本地shell脚本,并获取脚本的输出结果。
二、用法
执行python有两种常见的方法:一种是直接执行python,一种是通过执行shell脚本来执行python。
2.1 直接执行python
详见参考2
demo1: 先写好要执行的python文件, fib.py
# fib.py
def fib(n):
if n <= 2:
return 1
return fib(n-1) + fib(n-2)
demo2: 写go,调用python模块以及函数,然后执行
func main() {
m := python.PyImport_ImportModule("sys")
if m == nil {
fmt.Println("import error")
return
}
path := m.GetAttrString("path")
if path == nil {
fmt.Println("get path error")
return
}
//加入当前目录,空串表示当前目录
currentDir := python.PyString_FromString("")
python.PyList_Insert(path, 0, currentDir)
m = python.PyImport_ImportModule("fib") //加载python的模块,文件名
if m == nil {
fmt.Println("import error")
return
}
fib := m.GetAttrString("fib")//加载python的方法
if fib == nil {
fmt.Println("get fib error")
return
}
out := fib.CallFunction(python.PyInt_FromLong(10))//调用python的方法,并传参
if out == nil {
fmt.Println("call fib error")
return
}
fmt.Printf("fib(%d)=%d\n", 10, python.PyInt_AsLong(out))
}
异常场景
Package python-2.7 was not found in the pkg-config search path
解决方法:
执行以下命令:
pkg-config --list-all | grep python
如果结果为空,说明包配置里没有python的配置,可以通过以下方式解决:
# centos
yum install python-devel
# ubuntu
apt-get install python-dev
2.2 通过调用shell间接执行python
demo1:
func main() {
cmd := exec.Command("ls", "-lah")
out, err := cmd.CombinedOutput()
if err != nil {
log.Fatalf("cmd.Run() failed with %s\n", err)
}
fmt.Printf("combined out:\n%s\n", string(out))
demo2:
func main() {
cmd := exec.Command("ls", "-lah")
var stdout, stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr
err := cmd.Run()
if err != nil {
log.Fatalf("cmd.Run() failed with %s\n", err)
}
outStr, errStr := string(stdout.Bytes()), string(stderr.Bytes())
fmt.Printf("out:\n%s\nerr:\n%s\n", outStr, errStr)
上面是通过exec.Command的方式调用shell命令或者脚本,demo1通过cmd.CombineOutput的方式获取进程的输出以及错误信息,demo2通过重定向到标准输出,标准错误从而获取。这两种方法因为封装的比较好,操作比较简单。 下面讲一下通过开启一个新的进程来运行的方式
demo3: startProcess调用, 详见参考4
const (
_LOG_FILE = "out.log"
)
func readLines(path string) ([]string, int, error) {
file, err := os.Open(path)
if err != nil {
return nil,0, err
}
defer file.Close()
var lines []string
linecount :=0
scanner := bufio.NewScanner(file)
for scanner.Scan() {
lines = append(lines, scanner.Text())
linecount++
}
return lines,linecount,scanner.Err()
}
func StartProcessExecShell() {
cmdToRun := "./test.sh"
//cmdToRun := "/path/to/someCommand"
args := []string{" ", " "}
procAttr := new(os.ProcAttr)
//打开一个 *File
stdOut, _ := os.OpenFile(_LOG_FILE, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)
procAttr.Files = []*os.File{os.Stdin, stdOut, os.Stderr}
process, err := os.StartProcess(cmdToRun, args, procAttr);
//fmt.Printf("ERROR Unable to run %s: %s\n", cmdToRun, err.Error())
//go os.StartProcess(cmdToRun, args, procAttr)
if err != nil{
fmt.Printf("ERROR Unable to run %s: %s\n", cmdToRun, err.Error())
return
}
fmt.Printf("%s running as pid %d\n", cmdToRun, process.Pid)
process.Wait()
outputStr, _, err := readLines("./out.log")
if err != nil {
//log.Fatalf("error: %v", err)
fmt.Println("error = ", err)
}
fmt.Println("final result = ",outputStr)
}
简单讲解一下上面的代码, os.StartProcess开启一个进程去执行传入的命令, 它的输出可以指定输出到文件,也可以指定到标准输出(demo中所示的是指定输出到本地的文件out.log),最后在主进程里调用process.Wait()等待子进程处理完,然后打印输出。网上大部分博客都没有讲解如何获取os.StartProcess的输出,大部分只是打印一下进程id(Pid)。
执行shell遇到Exec format error
检查shell 脚本的正确格式是否如下:
#! /bin/bash
...
三、总结
1.跨进程,不同语言,最好还是通过rpc的方式去调用,go是静态语言,python是动态语言,可以通过go-python包来实现go直接调用python的方式,但是不优雅,也不好调试,不好拓展,同时也拖慢了go的性能;
2.go执行shell脚本一般有两种方式,exec.Command和os.StartProcess,其中cmd的方式比较方便获取子进程的结果
四、参考
https://studygolang.com/articles/11128
https://zhuanlan.zhihu.com/p/33445304
https://colobu.com/2017/06/19/advanced-command-execution-in-Go-with-os-exec/
http://lierhua.top/2019/02/03/golang%E5%88%9B%E5%BB%BA%E8%BF%9B%E7%A8%8BStartProcess/
进程原理
我们今天的关于从Shell脚本调用Python函数和shell脚本调用python脚本的分享就到这里,谢谢您的阅读,如果想了解更多关于bash – 如何将stdin从shell脚本重定向到shell脚本中的命令?、bash – 无法从shell脚本调用Openscad -D命令行、bash – 通过sudo – 环境变量从另一个shell脚本调用shell脚本?、go执行python/shell脚本的相关信息,可以在本站进行搜索。
本文标签: