简体   繁体   English

从JSON文档在Python中执行Shell脚本

[英]Executing a shell script in Python from the JSON document

I am trying to execute the shell script in Python using subprocess module. 我正在尝试使用子进程模块在Python中执行Shell脚本。

Below is my shell script which is called as testing.sh . 下面是我的shell脚本,称为testing.sh

#!/bin/bash

hello=$jj1

echo $hello

echo $jj1
echo $jj2

for el1 in $jj3
do
    echo "$el1"
done

for el2 in $jj4
do
    echo "$el2"
done

Now I am trying to execute the above shell script in Python so I did like this - 现在,我试图在Python中执行上述Shell脚本,所以我做到了-

subprocess.call(['./testing.sh'])

and it works fine. 而且效果很好。 Now I am thinking to add the above script in a JSON document like this and then execute it - 现在,我正在考虑将上述脚本添加到这样的JSON文档中,然后执行它-

json_script = '{"script":"above testing.sh script here"}'
j = json.loads(json_script)
shell_script = j['script']
subprocess.call(shell_script, shell=True)

But everytime I am trying, it is giving me an error - 但是每次我尝试时,都会给我一个错误-

Below is my full Python script which contains the above testing.sh shell script in a JSON document - 以下是我的完整Python脚本,其中包含JSON文档中的上述testing.sh shell脚本-

#!/usr/bin/python

import subprocess
import json
import socket
import os

jsonData = '{"pp": [0,3,5,7,9], "sp": [1,2,4,6,8]}'
jj = json.loads(jsonData)

print jj['pp']
print jj['sp']

os.putenv( 'jj1',  'Hello World 1')
os.putenv( 'jj2',  'Hello World 2')
os.putenv( 'jj3', ' '.join( str(v) for v in jj['pp']  ) )
os.putenv( 'jj4', ' '.join( str(v) for v in jj['sp']  ) )

print "start"

jsonDataaa = '{"script":"#!/bin/bash \\n hello=$jj1 \\n echo $hello \\n echo $jj1 \\n echo $jj2 \\n for el1 in $jj3 \\n do \\n echo "$el1" \\n done \\n for el2 in $jj4 \\n do \\n echo "$el2" \\n done"}'
j = json.loads(jsonDataaa)

shell_script = j['script']
print "start"
subprocess.call(shell_script, shell=True)
print "end"

And below is the error I am getting - 下面是我得到的错误-

 File "C:\Python27\lib\json\__init__.py", line 338, in loads
    return _default_decoder.decode(s)
  File "C:\Python27\lib\json\decoder.py", line 365, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "C:\Python27\lib\json\decoder.py", line 381, in raw_decode
    obj, end = self.scan_once(s, idx)
ValueError: Expecting , delimiter: line 1 column 113 (char 112) 

And the expected output I should be getting like this - 和预期的输出,我应该是这样的-

[0, 3, 5, 7, 9]
[1, 2, 4, 6, 8]
start
Hello World 1
Hello World 2
0
3
5
7
9
1
2
4
6
8
end

UPDATE:- 更新:-

If I have my jsonDataaa like this 如果我有这样的jsonDataaa

jsonDataaa = '{"script":"#!/bin/bash \\n hello=$jj1 \\n echo $hello \\n echo $jj1 \\n echo $jj2 \\n"}'

then it works fine... And I am able to execute it properly.. But if my jsonDataaa is as I mentioned in my question, then only it gives me an error. 然后它可以正常工作...而且我能够正确执行它。.但是,如果我的jsonDataaa如我在问题中提到的那样,那么只有它会给我一个错误。 I am thinking there might be some syntax error which I am not able to understand. 我认为可能存在某些语法错误,我无法理解。

It gives you this error because your json string is invalid. 由于您的json字符串无效,因此会出现此错误。 Specifically, it contains unescaped quotes. 具体来说,它包含未转义的引号。

It works if you replace your jsonDataaa assignment with: 如果您将jsonDataaa分配替换为:

jsonDataaa = '{"script":"#!/bin/bash \\n hello=$jj1 \\n echo $hello \\n echo $jj1 \\n echo $jj2 \\n for el1 in $jj3 \\n do \\n echo \\"$el1\\" \\n done \\n for el2 in $jj4 \\n do \\n echo \\"$el2\\" \\n done"}'

This part doesn't quite make sense: 这部分不太有意义:

jsonDataaa = '{"script":"#!/bin/bash \\n hello=$jj1 \\n echo $hello \\n echo $jj1 \\n echo $jj2 \\n for el1 in $jj3 \\n do \\n echo "$el1" \\n done \\n for el2 in $jj4 \\n do \\n echo "$el2" \\n done"}'
j = json.loads(jsonDataaa)

shell_script = j['script']
print "start"
subprocess.call(shell_script, shell=True)

What you've done here is pass a literal string as the argument to subprocess.call(), but it expects a program name, not program text. 您在此处所做的是将文字字符串作为参数传递给subprocess.call(),但它需要程序名称,而不是程序文本。 So you have a couple choices: you could write the contents of shell_script to a NamedTemporaryFile and execute that, or you could launch a piped bash in subprocess and feed its stdin from shell_script as a string. 因此,您有两种选择:可以将shell_script的内容写入NamedTemporaryFile并执行,或者可以在子shell_script启动管道bash并将shell_script stdin作为字符串输入。 That latter approach is what I'd prefer, and you can get more help to do it here: Python - How do I pass a string into subprocess.Popen (using the stdin argument)? 我更喜欢使用后一种方法,您可以在此处获得更多帮助: Python-如何将字符串传递到subprocess.Popen中(使用stdin参数)?

PS: if you use a triple-quoted string you can make your JSON look a lot nicer, on multiple lines and whatnot. PS:如果您使用三引号引起来的字符串,则可以使您的JSON看起来更好,可以在多行上显示。

You could also do: 您也可以这样做:

subprocess.call(["/bin/sh", "-c", shell_script])

You are passing the whole script as a single command-line parameter to sh. 您正在将整个脚本作为单个命令行参数传递给sh。 This should work even if there are newlines in shell_script; 即使shell_script中有换行符,它也应该起作用。 but if it's more than a certain size (16K bytes? something like that) it won't fit in a command line. 但是,如果它大于某个大小(16K字节?类似的东西),它将不适合在命令行中使用。

EDIT - by using subprocess.call(shell_script, shell=True) it actually amounts to the same as what I've suggested, more or less (perhaps the effect of other options might be different). 编辑-通过使用subprocess.call(shell_script, shell=True)它实际上与我建议的相同,或多或少(也许其他选项的效果可能不同)。 So now I'm guessing the quoting of the \\n etc may be incorrect as you've hinted at - see comments below. 因此,现在我猜想\\ n等的引用可能不正确,如您所暗示-请参阅下面的注释。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM