Consider I have two python scripts caller.py and being_called.py
Caller.py:
p = Popen(path_to_being_called, shell=True, stdout=fh, stderr=fh1)
path_to_being_called contains executable path of script 'being_called.py'
Now being_called.py does following:
os.environ['hello'] = 'Yolo'
I want to access this value of environment variable hello inside the script caller.py
Is there a way to do this with popen calls?
Note that I know I can update environment variable for 'being_called' from caller itself as a paramter env and mapping of os.environ and kwargs, but thats not what I want to do. Env variable will be updated from being_called.py only and I need to access its value in caller.py
I tried to see what dir(p) offers but not getting any help from any of that.
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 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 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.
I am sorry if my question not very clear.
I am trying to create a variable pass it to the environment in linux. Then, I want to be able to get this variable some where else. What i have tried so far on the linux command line:
local_pc:~/home$ export variable=10
local_pc:~/home$ python -c 'import os; print os.getenv("variable")'
10
which all sound fine. But when I set export in python I will not be able to get it
subprocess.call(["export","variable=20"],shell = True)
print(os.getenv("variable"))
None
So my question here is how to do xport variable=10 in python
You can change environment variable only for current process or its children. To change environment in its parent process would require hacks e.g., using gdb.
In your example export variable=10 is run in the same process and python -c .. command is a child process (of the shell). Therefore it works.
In your Python example, you are trying (incorrectly) to export variable in a child process and get it in a parent process.
To summarize:
working example: parent sets environment variable for a child
non-working example: child tries to set environment variable for a parent
To reproduce your bash example:
import os
import sys
from subprocess import check_call
#NOTE: it works but you shouldn't do it, there are most probably better ways
os.environ['variable'] = '10' # set it for current processes and its children
check_call([sys.executable or 'python', '-c',
'import os; print(os.getenv("variable"))'])
Subprocess either inherits parent's environment or you could set it explicitly using env argument.
For example, to change a local timezone that is used by time module, you could change TZ environment variable for the current python process on posix systems:
import os
import time
os.environ['TZ'] = ':America/New_York'
time.tzset()
is_dst = time.daylight and time.localtime().tm_isdst > 0
# local time = utc time + utc offset
utc_offset = -time.timezone if not is_dst else -time.altzone
print("%s has utc offset: %.1f hours" % (
os.environ.get('TZ').lstrip(':'), utc_offset/3600.))
update:
There's no feasible way to establish commuication over processes through environment variables.
The child may inherit the environment variables from the parent, but a change to the parent environment variables after the childs invocation won't be passed through to the child and the child's environment changes are completely intransparent to the parent. So no way!
I tested it by trying to establish a round-robin, token-based message passing approach, but i don't see a way to get the changes passed between the process environment variables.