Let's say I have a python script located at C:\script.py. This is the contents of the script:
def func1(arg1):
print (arg1)
if __name__ == "__main__":
func1(arg1)
Now, I want to run this script using Robot Framework. I'm thinking about doing something like this:
*** Test Cases ***
Test1
Run Process python C:\script.py ${arg1}
But it doesn't work. How can I run this script, and pass an argument to it?
It would be nicer if you have posted a real example that we could experiment, to understand:
But it doesn't work.
As you can see in the documentation of Run Process, you have to redirect the output of your process, so you can see it (if that was your problem).
Here is a working example based on yours:
import sys
arg1 = sys.argv[1] or None
def func1(argument):
print(argument)
if __name__ == "__main__":
func1(arg1)
*** Settings ***
Library Process
*** Test Cases ***
Test1
Run Process python C:/script.py This is my argument to script. stdout=C:/script_output.log
But maybe the best solution is to make your script as a Keyword.
First, you will have to modify your script to use command line arguments which you can find in sys.argv.
For example:
import sys
def func1(arg1):
print (arg1)
if __name__ == "__main__":
func1(sys.argv[1])
Next, you must make sure to have two or more spaces between script.py and the argument:
Run Process python C:\\script.py ${arg1}
And, of course, you need to define what ${arg1} is, which you didn't do in your example.
I agree with #Helio, making python program as a keyword will be faster and easy solution to implement.
Import py script in settings section under Library.
${result}= func1 arg1
Here func1 act as a keyword to do whatever it is suppose to do as a function. Then result variable will capture the output which then can be logged or printed to console.
Related
I have a Python program I'm building that can be run in either of 2 ways: the first is to call python main.py which prompts the user for input in a friendly manner and then runs the user input through the program. The other way is to call python batch.py -file- which will pass over all the friendly input gathering and run an entire file's worth of input through the program in a single go.
The problem is that when I run batch.py, it imports some variables/methods/etc from main.py, and when it runs this code:
import main
at the first line of the program, it immediately errors because it tries to run the code in main.py.
How can I stop Python from running the code contained in the main module which I'm importing?
Because this is just how Python works - keywords such as class and def are not declarations. Instead, they are real live statements which are executed. If they were not executed your module would be empty.
The idiomatic approach is:
# stuff to run always here such as class/def
def main():
pass
if __name__ == "__main__":
# stuff only to run when not called via 'import' here
main()
It does require source control over the module being imported, however.
Due to the way Python works, it is necessary for it to run your modules when it imports them.
To prevent code in the module from being executed when imported, but only when run directly, you can guard it with this if:
if __name__ == "__main__":
# this won't be run when imported
You may want to put this code in a main() method, so that you can either execute the file directly, or import the module and call the main(). For example, assume this is in the file foo.py.
def main():
print "Hello World"
if __name__ == "__main__":
main()
This program can be run either by going python foo.py, or from another Python script:
import foo
...
foo.main()
Use the if __name__ == '__main__' idiom -- __name__ is a special variable whose value is '__main__' if the module is being run as a script, and the module name if it's imported. So you'd do something like
# imports
# class/function definitions
if __name__ == '__main__':
# code here will only run when you invoke 'python main.py'
Unfortunately, you don't. That is part of how the import syntax works and it is important that it does so -- remember def is actually something executed, if Python did not execute the import, you'd be, well, stuck without functions.
Since you probably have access to the file, though, you might be able to look and see what causes the error. It might be possible to modify your environment to prevent the error from happening.
Put the code inside a function and it won't run until you call the function. You should have a main function in your main.py. with the statement:
if __name__ == '__main__':
main()
Then, if you call python main.py the main() function will run. If you import main.py, it will not. Also, you should probably rename main.py to something else for clarity's sake.
There was a Python enhancement proposal PEP 299 which aimed to replace if __name__ == '__main__': idiom with def __main__:, but it was rejected. It's still a good read to know what to keep in mind when using if __name__ = '__main__':.
You may write your "main.py" like this:
#!/usr/bin/env python
__all__=["somevar", "do_something"]
somevar=""
def do_something():
pass #blahblah
if __name__=="__main__":
do_something()
I did a simple test:
#test.py
x = 1
print("1, has it been executed?")
def t1():
print("hello")
print("2, has it been executed?")
def t2():
print("world")
print("3, has it been executed?")
def main():
print("Hello World")
print("4, has it been executed?")
print("5, has it been executed?")
print(x)
# while True:
# t2()
if x == 1:
print("6, has it been executed?")
#test2.py
import test
When executing or running test2.py, the running result:
1, has it been executed?
5, has it been executed?
1
6, has it been executed?
Conclusion: When the imported module does not add if __name__=="__main__":, the current module is run, The code in the imported module that is not in the function is executed sequentially, and the code in the function is not executed when it is not called.
in addition:
def main():
# Put all your code you need to execute directly when this script run directly.
pass
if __name__ == '__main__':
main()
else:
# Put functions you need to be executed only whenever imported
A minor error that could happen (at least it happened to me), especially when distributing python scripts/functions that carry out a complete analysis, was to call the function directly at the end of the function .py file.
The only things a user needed to modify were the input files and parameters.
Doing so when you import you'll get the function running immediately. For proper behavior, you simply need to remove the inside call to the function and reserve it for the real calling file/function/portion of code
Another option is to use a binary environment variable, e.g. lets call it 'run_code'. If run_code = 0 (False) structure main.py to bypass the code (but the temporarily bypassed function will still be imported as a module). Later when you are ready to use the imported function (now a module) set the environment variable run_code = 1 (True). Use the os.environ command to set and retrieve the binary variable, but be sure to convert it to an integer when retrieving (or restructure the if statement to read a string value),
in main.py:
import os
#set environment variable to 0 (False):
os.environ['run_code'] = '0'
def binary_module():
#retrieve environment variable, convert to integer
run_code_val = int(os.environ['run_code'] )
if run_code_val == 0:
print('nope. not doing it.')
if run_code_val == 1:
print('executing code...')
# [do something]
...in whatever script is loading main.py:
import os,main
main.binary_module()
OUTPUT: nope. not doing it.
# now flip the on switch!
os.environ['run_code'] = '1'
main.binary_module()
OUTPUT: executing code...
*Note: The above code presumes main.py and whatever script imports it exist in the same directory.
Although you cannot use import without running the code; there is quite a swift way in which you can input your variables; by using numpy.savez, which stores variables as numpy arrays in a .npz file. Afterwards you can load the variables using numpy.load.
See a full description in the scipy documentation
Please note this is only the case for variables and arrays of variable, and not for methods, etc.
Try just importing the functions needed from main.py? So,
from main import SomeFunction
It could be that you've named a function in batch.py the same as one in main.py, and when you import main.py the program runs the main.py function instead of the batch.py function; doing the above should fix that. I hope.
I have a Python program I'm building that can be run in either of 2 ways: the first is to call python main.py which prompts the user for input in a friendly manner and then runs the user input through the program. The other way is to call python batch.py -file- which will pass over all the friendly input gathering and run an entire file's worth of input through the program in a single go.
The problem is that when I run batch.py, it imports some variables/methods/etc from main.py, and when it runs this code:
import main
at the first line of the program, it immediately errors because it tries to run the code in main.py.
How can I stop Python from running the code contained in the main module which I'm importing?
Because this is just how Python works - keywords such as class and def are not declarations. Instead, they are real live statements which are executed. If they were not executed your module would be empty.
The idiomatic approach is:
# stuff to run always here such as class/def
def main():
pass
if __name__ == "__main__":
# stuff only to run when not called via 'import' here
main()
It does require source control over the module being imported, however.
Due to the way Python works, it is necessary for it to run your modules when it imports them.
To prevent code in the module from being executed when imported, but only when run directly, you can guard it with this if:
if __name__ == "__main__":
# this won't be run when imported
You may want to put this code in a main() method, so that you can either execute the file directly, or import the module and call the main(). For example, assume this is in the file foo.py.
def main():
print "Hello World"
if __name__ == "__main__":
main()
This program can be run either by going python foo.py, or from another Python script:
import foo
...
foo.main()
Use the if __name__ == '__main__' idiom -- __name__ is a special variable whose value is '__main__' if the module is being run as a script, and the module name if it's imported. So you'd do something like
# imports
# class/function definitions
if __name__ == '__main__':
# code here will only run when you invoke 'python main.py'
Unfortunately, you don't. That is part of how the import syntax works and it is important that it does so -- remember def is actually something executed, if Python did not execute the import, you'd be, well, stuck without functions.
Since you probably have access to the file, though, you might be able to look and see what causes the error. It might be possible to modify your environment to prevent the error from happening.
Put the code inside a function and it won't run until you call the function. You should have a main function in your main.py. with the statement:
if __name__ == '__main__':
main()
Then, if you call python main.py the main() function will run. If you import main.py, it will not. Also, you should probably rename main.py to something else for clarity's sake.
There was a Python enhancement proposal PEP 299 which aimed to replace if __name__ == '__main__': idiom with def __main__:, but it was rejected. It's still a good read to know what to keep in mind when using if __name__ = '__main__':.
You may write your "main.py" like this:
#!/usr/bin/env python
__all__=["somevar", "do_something"]
somevar=""
def do_something():
pass #blahblah
if __name__=="__main__":
do_something()
I did a simple test:
#test.py
x = 1
print("1, has it been executed?")
def t1():
print("hello")
print("2, has it been executed?")
def t2():
print("world")
print("3, has it been executed?")
def main():
print("Hello World")
print("4, has it been executed?")
print("5, has it been executed?")
print(x)
# while True:
# t2()
if x == 1:
print("6, has it been executed?")
#test2.py
import test
When executing or running test2.py, the running result:
1, has it been executed?
5, has it been executed?
1
6, has it been executed?
Conclusion: When the imported module does not add if __name__=="__main__":, the current module is run, The code in the imported module that is not in the function is executed sequentially, and the code in the function is not executed when it is not called.
in addition:
def main():
# Put all your code you need to execute directly when this script run directly.
pass
if __name__ == '__main__':
main()
else:
# Put functions you need to be executed only whenever imported
A minor error that could happen (at least it happened to me), especially when distributing python scripts/functions that carry out a complete analysis, was to call the function directly at the end of the function .py file.
The only things a user needed to modify were the input files and parameters.
Doing so when you import you'll get the function running immediately. For proper behavior, you simply need to remove the inside call to the function and reserve it for the real calling file/function/portion of code
Another option is to use a binary environment variable, e.g. lets call it 'run_code'. If run_code = 0 (False) structure main.py to bypass the code (but the temporarily bypassed function will still be imported as a module). Later when you are ready to use the imported function (now a module) set the environment variable run_code = 1 (True). Use the os.environ command to set and retrieve the binary variable, but be sure to convert it to an integer when retrieving (or restructure the if statement to read a string value),
in main.py:
import os
#set environment variable to 0 (False):
os.environ['run_code'] = '0'
def binary_module():
#retrieve environment variable, convert to integer
run_code_val = int(os.environ['run_code'] )
if run_code_val == 0:
print('nope. not doing it.')
if run_code_val == 1:
print('executing code...')
# [do something]
...in whatever script is loading main.py:
import os,main
main.binary_module()
OUTPUT: nope. not doing it.
# now flip the on switch!
os.environ['run_code'] = '1'
main.binary_module()
OUTPUT: executing code...
*Note: The above code presumes main.py and whatever script imports it exist in the same directory.
Although you cannot use import without running the code; there is quite a swift way in which you can input your variables; by using numpy.savez, which stores variables as numpy arrays in a .npz file. Afterwards you can load the variables using numpy.load.
See a full description in the scipy documentation
Please note this is only the case for variables and arrays of variable, and not for methods, etc.
Try just importing the functions needed from main.py? So,
from main import SomeFunction
It could be that you've named a function in batch.py the same as one in main.py, and when you import main.py the program runs the main.py function instead of the batch.py function; doing the above should fix that. I hope.
Running: Windows 7, python 3.4 & 2.7
In one of my nosetests plugin, (one that post test data to a website), I need to ascertain if the test is being run with the --failed option or without. If --failed is enabled, that means this test failed the first time and is being run once more to see if that fail was a fluke. If this is a re-run of a failed test I need to direct my plugin to some different behavior vs. if the test is being run for the first time.
In other words, I want to ascertain inside the plugin if we are inside nosetests or nosetests --failed.
How can I access nosetest's command line options from inside a plug in? What variable are the options stored in?
My eventual code will look something like this:
if <--failed option was invoked with nosetests command>:
do something
else:
do something different
What's the correct code to replace what's inside <>?
I don't fully understand, but the command line arguments part is easy. Just use the following code:
from sys import argv as arguments
if "--failed" in arguments :
do_something()
else :
do_something_else()
When you import sys, you have access to the sys.argv
The simplest way to grab command line arguments is the system library
import sys
sys.argv #this is a list of args sys.argv[0] is the program itself
so it would be
if sys.argv[1] == '--failed':
I just want to have some ideas to know how to do that...
I have a python script that parses log files, the log name I give it as an argument so that when i want to run the script it's like that.. ( python myscript.py LOGNAME )
what I'd like to do is to have two scripts one that contains the functions and another that has only the main function so i don't know how to be able to give the argument when i run it from the second script.
here's my second script's code:
import sys
import os
path = "/myscript.py"
sys.path.append(os.path.abspath(path))
import myscript
mainFunction()
the error i have is:
script, name = argv
valueError: need more than 1 value to unpack
Python (just as most languages) will share parameters across imports and includes.
Meaning that if you do:
python mysecondscript.py heeey that will flow down into myscript.py as well.
So, check your arguments that you pass.
Script one
myscript = __import__('myscript')
myscript.mainfunction()
script two
import sys
def mainfunction():
print sys.argv
And do:
python script_one.py parameter
You should get:
["script_one.py", "parameter"]
You have several ways of doing it.
>>> execfile('filename.py')
Check the following link:
How to execute a file within the python interpreter?
I need to execute a python script from within another python-script multiple times with different arguments.
I know this sounds horrible but there are reasons for it.
Problem is however that the callee-script does not check if it is imported or executed (if __name__ == '__main__': ...).
I know I could use subprocess.popen("python.exe callee.py -arg") but that seems to be much slower then it should be, and I guess thats because Python.exe is beeing started and terminated multiple times.
I can't import the script as a module regularily because of its design as described in the beginning - upon import it will be executed without args because its missing a main() method.
I can't change the callee script either
As I understand it I can't use execfile() either because it doesnt take arguments
Found the solution for you. You can reload a module in python and you can patch the sys.argv.
Imagine echo.py is the callee script you want to call a multiple times :
#!/usr/bin/env python
# file: echo.py
import sys
print sys.argv
You can do as your caller script :
#!/usr/bin/env python
# file: test.py
import sys
sys.argv[1] = 'test1'
import echo
sys.argv[1] = 'test2'
reload(echo)
And call it for example with : python test.py place_holder
it will printout :
['test.py', 'test1']
['test.py', 'test2']