I am using Centos 7.0 and PyDEv in Eclipse. I am trying to pass the variable in Python into c shell script. But I am getting error:
This is my Python script named raw2waveconvert.py
num = 10
print(num)
import subprocess
subprocess.call(["csh", "./test1.csh"])
Output/Error when I run the Python script:
10
num: Undefined variable.
The file test1.csh contains:
#!/bin/csh
set nvar=`/home/nishant/workspace/codec_implement/src/NTTool/raw2waveconvert.py $num`
echo $nvar
Okey, so apparently it's not so easy to find a nice and clear duplicate. This is how it's usually done. You either pass the value as an argument to the script, or via an environmental variable.
The following example shows both ways in action. Of course you can drop whatever you don't like.
import subprocess
import shlex
var = "test"
env_var = "test2"
script = "./var.sh"
#prepare a command (append variable to the scriptname)
command = "{} {}".format(script, var)
#prepare environment variables
environment = {"test_var" : env_var}
#Note: shlex.split splits a textual command into a list suited for subprocess.call
subprocess.call( shlex.split(command), env = environment )
This is corresponding bash script, but from what I've read addressing command line variables is the same, so it should work for both bash and csh set as default shells.
var.sh:
#!/bin/sh
echo "I was called with a command line argument '$1'"
echo "Value of enviormental variable test_var is '$test_var'"
Test:
luk32$ python3 subproc.py
I was called with a command line argument 'test'
Value of enviormental variable test_var is 'test2'
Please note that the python interpreter needs to have appropriate access to the called script. In this case var.sh needs to be executable for the user luk32. Otherwise, you will get Permission denied error.
I also urge to read docs on subprocess. Many other materials use shell=True, I won't discuss it, but I dislike and discourage it. The presented examples should work and be safe.
subprocess.call(..., env=os.environ + {'num': num})
The only way to do what you want here is to export/pass the variable value through the shell environment. Which requires using the env={} dictionary argument.
But it is more likely that what you should do is pass arguments to your script instead of assuming pre-existing variables. Then you would stick num in the array argument to subprocess.call (probably better to use check_call unless you know the script is supposed to fail) and then use $1/etc. as normal.
Related
I'm working on cloning a Virtual Machine (VM) in vCenter environment using this code. It takes command line arguments for name of the VM, template, datastore, etc. (e.g. $ clone_vm.py -s <host_name> -p < password > -nossl ....)
I have another Python file where I've been able to list the Datastore volumes in descending order of free_storage. I have stored the datastore with maximum available storage in a variable ds_max. (Let's call this ds_info.py)
I would like to use ds_max variable from ds_info.py as a command line argument for datastore command line argument in clone_vm.py.
I tried importing the os module in ds_info.py and running os.system(python clone_vm.py ....arguments...) but it did not take the ds_max variable as an argument.
I'm new to coding and am not confident to change the clone_vm.py to take in the Datastore with maximum free storage.
Thank you for taking the time to read through this.
I suspect there is something wrong in your os.system call, but you don't provide it, so I can't check.
Generally it is a good idea to use the current paradigm, and the received wisdom (TM) is that we use subprocess. See the docs, but the basic pattern is:
from subprocess import run
cmd = ["mycmd", "--arg1", "--arg2", "val_for_arg2"]
run(cmd)
Since this is just a list, you can easily drop arguments into it:
var = "hello"
cmd = ["echo", var]
run(cmd)
However, if your other command is in fact a python script it is more normal to refactor your script so that the main functionality is wrapped in a function, called main by convention:
# script 2
...
def main(arg1, arg2, arg3):
do_the_work
if __name__ == "__main__":
args = get_sys_args() # dummy fn
main(*args)
Then you can simply import script2 from script1 and run the code directly:
# script 1
from script2 import main
args = get_args() # dummy fn
main(*args)
This is 'better' as it doesn't involve spawning a whole new python process just to run python code, and it generally results in neater code. But nothing stops you calling a python script the same way you'd call anything else.
I have a python script a.py that returns a tuple of two values.
I am running this script from a Jenkins bash shell and I need to be able to retrieve the return values and use them in the further steps of the job.
As of now, the call to the script looks like:
ret_tuple=($($ENV_PATH/bin/python a.py))
Then I am trying to access the return value and assign it to variables that later I would inject into the Jenkins job
echo "${ret_tuple[0]}"
echo "${ret_tuple[1]}"
echo SRC_BUCKET=${ret_tuple[0]} > variables.properties
echo DST_BUCKET=${ret_tuple[1]} > variables.properties
Later, I forward these variables into another job that this job triggers and I can see that the parameters that are being sent from the variables are incorrect.
One of them holds $SRC_BUCKET and the second one Disabled! (which doesn't make a lot of sense to me).
I pass the variables like that:
data_path=${SRC_BUCKET}
destination_path=${DST_BUCKET}
Am I doing this in the right way and I should look for the problem in another place? or there's something wrong with this variable assignment above?
EDIT:
The python script returns two strings
src_bucket_path = os.path.join(export_path, file_name)
dst_bucket_path = os.path.join(destination_path, dst_bucket_suffix_path)
return src_bucket_path, dst_bucket_path
Maybe use command expansion, so the command is evaluated before outputted into the variables.properties files.
$(echo SRC_BUCKET=${ret_tuple[0]} > variables.properties)
$(echo DST_BUCKET=${ret_tuple[1]} > variables.properties)
A good article for you to read,
http://www.compciv.org/topics/bash/variables-and-substitution/
If you run your scripts in the same shell session window, you could create an environment variable from one script, and then when you run the next script you can access the environment variable.
I am trying to execute a command from lua script. The command is to simply run a python script named "sha_compare.py" of which receives 3 arguments where two of them are variables from the lua script - dady_data and sha:
local method = ngx.var.request_method
local headers = ngx.req.get_headers()
if method == "POST" then
ngx.req.read_body()
local body_data = ngx.req.get_body_data()
local sha = headers['X-Hub-Signature-256']
ngx.print(os.execute("python3 sha_compare.py"..sha..body_data))
else
The script fails because of the way I call the arguments. The actual command if I would have ran it from cmd would have been something like:
python3 python3 sha_compare.py sha256=ffs8df aaaaa
Please tell me how should I change my code to call the python script with 3 vars properly.
If it is not possible or hard to implement, please let me know how can I call a .sh script which will receive those 3 params.
You're not providing spaces between the arguments: you're trying to execute
python3 sha_compare.pysha256=ffs8dfaaaaa
Do this:
os.execute("python3 sha_compare.py "..sha.." "..body_data)
It's often easier to build the command up as a table, and the concat it for execution:
local cmd = { 'python3', 'sha_compare.py', sha, body_data }
os.execute(table.concat(cmd, " "))
I would like to know how can i use my variables in output of another command. For example if i try to generate some keys with "openssl" i'll get the question about the country, state, organizations etc.
I would like to use my variables in the script that i have to fill this information. I'll have variable "Country"; variable "State" etc. and to be parsed/set in to this questions from the openssl command when is executed.
I'm trying this in bash but also would like to know how will be the same think done in python.
Kind regards
You have multiple ways to do so.
1. If you have your script launched before the python script and the result set in an enviroment variable you can read the environment variable from your python script as follows:
import os
os.environ.get('MYVARIABLE', 'Default val')
Otherwise you can try to launch the other application from your python script and read the result by using os.popen():
import os
tmp = os.popen("ls").read()
or better (if you have a python newer than 2.6)
import subprocess
proc = subprocess.Popen('ls', stdout=subprocess.PIPE)
tmp = proc.stdout.read()
I am working on a project with Python in which I am supposed to execute shell script with Python.
I have written a simple program from which I am able to execute shell script with my python code. But now I need to pass certain parameters from my Python code to the shell script and then print out those parameters by executing the shell script.
For the simplicity sake, Currently I am executing shell script which will print out Hello World but now I want to pass hostname and pp and sp values to my shell script and then print out those values from the shell script when it is getting execute by Python client.
#!/usr/bin/python
import subprocess
import json
import socket
hostname = socket.gethostname()
jsonData = '{"desc": "some information about the host", "pp": [0,3,5,7,9], "sp": [1,2,4,6,8]}'
jj = json.loads(jsonData)
print jj['pp'] # printing it from Python program for now
print jj['sp'] # printing it from Python program for now
print hostname # printing it from Python program for now
# pass the above values to my shell script
jsonStr = '{"script":"#!/bin/bash\\necho Hello World\\n"}'
j = json.loads(jsonStr)
print "start"
subprocess.call(j['script'], shell=True)
print "end"
In general, I want to pass, hostname, pp and sp values to my shell script as shown in jsonStr and then print out those values from the shell script itself when I run my Python code.
So it should print out like this whenever I execute my shell script in jsonStr-
start
Hello world
[0, 3, 5, 7, 9]
[1, 2, 4, 6, 8]
myhostname
end
Is this possible to do it in Python?
There are two ways to pass variables to a script: as arguments, or through the environment.
Since you're trying to execute a script as if it were a giant command line (which won't actually work—especially if you're escaping your newlines as \\n so the shell sees the whole thing as one line—but let's pretend it would), you can't pass arguments, so you will need to pass an environment.
This is trivial:
env = {}
env.update(os.environ)
env.update(jj)
subprocess.call('echo ${pp}', shell=True, env=env)
This will print out whatever was in jj[pp], and return 0.
Why? Well, in bash, ${pp} means "whatever is in the environment variable pp". And we copied every key-value pair from jj into the env environment, so the environment variable pp has whatever value was in jj[pp]. (In some cases you might want to quote things, e.g. "${pp}", but for echo there's no reason to do that, and without knowing what you're going to do in your real-life code I can't guess what you might need.)
If you actually had a script that you wanted to call, stored in a file, then of course you could pass it arguments the same way you do with any other program you run via subprocess, and inside the script you could reference them as $1, etc.
However, I don't see why you need to pass arguments to a script you're building on the fly. Just build the values into the script. While that's usually a bad idea, that's mainly because building a script on the fly is a bad idea, and you've already committed to that part for some reason. Format your strings in Python, where you have access to the full power of str.format or % (as you prefer), and the entire Python stdlib. For example:
script = 'echo {}'.format(shlex.quote(jj['pp']))
subprocess.call(script, shell=True)
Now the script doesn't have to do anything to access the value; it's hard-coded into the script.