I want to execute a method of my python class from groovy script.
This method have two parameter.
When i execute this command from terminal:
python -c 'import Myclass; Myclass.method("param1","param2")' it is working.
I use this groovy script code :
def cmd = "cd /path/to/the/folder && python -c 'import Myclass; Myclass.method(param1,param2)'"
def proc = ["/bin/sh", "-c", cmd].execute()
proc.waitFor()
println "return code: ${proc.exitValue()}"
println "stderr: ${proc.err.text}"
println "stdout: ${proc.in.text}"
When i want to do the same in the groovy script i have error with the parameter : NameError: name 'param1' is not defined.
Do you have any idea why ?
Best regards
When you executed the script in the terminal, you used the string literals "param1", "param2" , not the undefined variables param1, param2. Since you have already used both single and double quotes, you should escape the double quotes with a backslash:
def cmd = "cd /path && python -c 'import Myclass; Myclass.method(\"param1\", \"param2\")'"
or, just use the triple quotes:
def cmd = '''cd /path && python -c 'import Myclass; Myclass.method("param1", "param2")' '''
Related
I have a simple task and want to run command from the line.
E.g.
python3 -c 'print(2*2)'
The issue is when I want to invoke a function and pass parameter to it. E.g I want to lower the string 'ABC'.
I use
python3 -c 'print(x="ABC",x.lower())'
Hence my question: how could I pass string value to function when invoke python from command line?
Use sys.argv to obtain command-line arguments:
$ python3 -c "import sys; print(sys.argv[1].lower())" HELLO
hello
$
I am running a python3 script which performs the following snippet on Debian 9:
os.environ["PA_DIR"] = "/home/myname/some_folder"
command_template = ("sudo java -Dconfig.file=$PA_DIR/google.conf "
"-jar ~/big/cromwell-42.jar run $PA_DIR/WholeGenomeGermlineSingleSample.wdl "
"-i {} -o $PA_DIR/au_options.json > FDP{}.log 2>&1")
command = command_template.format("test.json, "1")
os.system("screen -dm -S S{} bash -c '{}'".format("1", command))
The use of PA_DIR works as intended. When I tried it on command line:
PA_DIR="/home/myname/some_folder"
screen -dm -S S1 bash -c 'sudo java -Dconfig.file=$PA_DIR/google.conf -jar ~/big/cromwell-42.jar run $PA_DIR/WholeGenomeGermlineSingleSample.wdl -i test.json -o $PA_DIR/au_options.json > FDP1.log 2>&1'
it doesn't do variable substitution due to single quotes and I had to replace them with double quotes (it complains it cannot find the file /google.conf).
What is different when python runs it?
Thanks!
The Python os.system() invokes the underlying system function of the C library, which on POSIX systems is equivalent to do something like
sh -c "your_command and all its arguments"
So the command and all arguments are already surrounded by double-quotes, which does environment variable substitution. Any single quotes inside the string is irrelevant for the variable substitution.
You can test it easily. In a shell do something like
$ foo="bar"
$ echo "foo is '$foo'" # Will print foo is 'bar'
$ echo 'foo is "$foo"' # Will print foo is "$foo"
Waiting for your answer to daltonfury42, I'd bet the problem is, when running in a command line, you are not exporting the PA_DIR environment variable so it is not present in the second bash interpreter. And it behaves different beacuse of what Mihir answered.
If you run
PA_DIR=foo
you only declare a bash variable but it is not an environment variable. Then
bash -c "echo $PA_DIR"
this will output foo because your current interpreter interpolates $PA_DIR and then raises a second bash process with the command echo foo. But
bash -c 'echo $PA_DIR'
this prevents your bash interpreter from interpolating it so it raises a second bash process with the comand echo $PA_DIR. But in this second process the variable PA_DIR does not exist.
If you start your journey running
export PA_DIR=foo
this will become an environment variable that will be accessible to children processes, thus
bash -c 'echo $PA_DIR'
will output foo because the nested bash interpreter has access to the variable even if the parent bash interpreter did not interpolate it.
The same is true for any kind of children process. Try running
PA_DIR=foo
python3 -c 'import os; print(os.environ.get("PA_DIR"))'
python3 -c "import os; print(os.environ.get('PA_DIR'))"
export PA_DIR=foo
python3 -c 'import os; print(os.environ.get("PA_DIR"))'
python3 -c "import os; print(os.environ.get('PA_DIR'))"
in your shell. No quotes are involved here!
When you use the os.environ dictionary in a Python script, Python will export the variables for you. That's why you will see the variable interpolated by either
os.system("bash -c 'echo $PA_DIR'")
or
os.system('bash -c "echo $PA_DIR"')
But beware that in each case it is either the parent or either the children shell process who is interpolating the variable.
You must understand your process tree here:
/bin/bash # but it could be a zsh, fish, sh, ...
|- /usr/bin/python3 # presumably
|- /bin/sh # because os.system uses that
|- /bin/bash
If you want an environment variable to exist in the most nested process, you must export it anywhere in the upper tree. Or in that very process.
I have three functions in a python file. I want to call a particular function from the python file through a shell script or through the terminal and pass an argument to that python function. Is there any way I can do that?
I tried python -c "exec(open(filename.py).read()); functionName()" but I don't know how to pass an argument.
How to run,
python -c "import a, sys; a.functionName(sys.argv[1])" "sampleString"
from a shell script?
#!/bin/bash
import os
def abracadabra_personal(project):
directory = "/srv/http/Personal/" + project
try:
if not os.path.exists(directory):
os.makedirs(directory)
except OSError:
print("Error! Couldn't create project folder : " + directory)
def sample():
print("Your argument was got.")
The above is my python code. And below is my shell script.
#!/bin/bash
# creates a personal project
function abracadabra_personal() {
cd
# python -c "import abracadabra, sys; abracadabra.sample(sys.argv[1])" $1
python -c "print("hi")"
echo $1
cd /srv/http/Personal/
}
# creates an office project
function abracadabra_office() {
cd
python abracadabra.py $1
cd /srv/http/Office/
}
# creates a learning project
function abracadabra_learning() {
cd
python abracadabra.py $1
cd /srv/http/Learning/
}
# creates a freelance project
function abracadabra_freelance() {
cd
python abracadabra.py $1
cd /srv/http/Freelance/
}
The command line arguments are available in sys.argv.
$ cat a.py
def functionName(arg):
print('my argument is {}'.format(arg))
$ python -c 'import a, sys; a.functionName(sys.argv[1])' 'hello world'
my argument is hello world
Alternatively, put an entry point in the Python script. Then you can call this Python module directly.
$ cat b.py
def functionName(arg):
print('my argument is {}'.format(arg))
if __name__ == '__main__':
import sys
functionName(sys.argv[1])
$ python -m b 'hello world'
my argument is hello world
If you have a shell variable in a shell script, remember to use double quotes around variable expansions.
argument='hello world'
…
python -m the_python_module "$argument"
I need to execute my python program from shell script so that the print commands in my python program will be exposed for reading from another program.
the shell script:
#!/bin/bash
if [ $# -lt 1 ] || [ $# -gt 2 ];then
echo "Usage: $0 APK <duration in seconds>"
exit 1;
fi
printf "$(python '/root/Desktop/DroidBox_4.1.1/scripts/droidbox.py' $1 $2 -c 'import sys; exec sys.stdin.read()')"
My python program should get the parametrs $1 and $2 but it doesn't recognize those as parametrs but taking -c and the command after it as the parametrs.
For answers like: getting the process input stream in my other project won't work for me. the only way that seems to be working is to use -c option and the command 'exec sys.stdin.read()'.
thank you.
It should work pretty well just the way you've written it. In a stripped down version here's what I get:
the (bash) test.sh script:
#!/bin/bash
python /tmp/test.py $1 $2
the (python) test.py script:
import sys
print "in python"
print sys.argv
and finally a shell session:
smassey#hacklabs:/tmp $ ./test.sh hello world
in python
['/tmp/test.py', 'hello', 'world']
As you can see, the bash script calls the python script which prints values to stdout so they're just as exposed as anything else directed to stdout:
smassey#hacklabs:/tmp $ ./test.sh hello world | grep python | tr 'a-z' 'A-Z'
IN PYTHON
The argparse module is very helpful as well. This allow you to add custom flags to your program (makes it more convenient to works with from a user's perspective as well).
I have this command as part of a bash script
$(python -c "import urllib, sys; print urllib.unquote(sys.argv[0])", "h%23g")
But when I run it, I get this:
-bash: -c: command not found
As though bash has missed reading the python, and is thinking -c is the name of the command. Exactly the same happens when using backticks.
How can I make bash recognise the python?
the Python command is returning the string "-c" from your $(...) structure, which bash then tries to execute.
for example
python -c "import urllib, sys; print urllib.unquote(sys.argv[0])"
prints "-c", so you are essentially asking bash to interpret $(-c), for which the error is valid.
I think you want something like the following:
$(python -c "import urllib, sys; print urllib.unquote(sys.argv[1])" "h%23g")
This will result in h#g, if this is all you have on a line then it will also attempt to run a command called h#g, so I'm assuming you are actually using this as a part of a larger command.
The issue with your version is that sys.argv[0] is the -c from the command, and urllib.unquote('-c') will just return '-c'.
From the documentation on sys.argv:
If the command was executed using the -c command line option to the interpreter, argv[0] is set to the string '-c'.
Combining that with info from the man page (emphasis mine):
-c command
Specify the command to execute (see next section). This terminates the option list (following options are passed as arguments to the command).
So, when you use -c, sys.argv[0] will be '-c', the argument provided to -c is the script so it will not be included in sys.argv, and any additional arguments are added to sys.argv starting at index 1.