I have a python script that has a method that takes in a string that contains another python script. I'd like to execute that script, call a function in it, and then use that function's results in my main script. It currently looks something like this:
def executePythonScript(self, script, param):
print 'Executing script'
try:
code = compile(script, '<string>', 'exec')
exec code
response = process(param)
except Exception as ex:
print ex
print 'Response: ' + response
return response
The "process" function is assumed to exist in the script that gets compiled and executed run-time.
This solution works well for VERY simple scripts, like:
def process():
return "Hello"
...but I'm having no luck getting more complex scripts to execute. For instance, if my script uses the json package, I get:
global name 'json' is not defined
Additionally, if my process function refers to another function in that same script, I'll get an error there as well:
def process():
return generateResponse()
def generateResponse():
return "Hello"
...gives me an error:
global name 'generateResponse' is not defined
Is this an issue of namespacing? How come json (which is a standard python package) does not get recognized? Any advice would be appreciated!
import subprocess
subprocess.call(["python","C:/path/to/my/script.py"])
I would recommend against this and just use import.
This is also under the assumption that your PYTHONPATH is set in your environment variables.
Related
I am trying to find a way to create a Windows shortcut that executes a function from a Python file.
The function being run would look something like this (it runs a command in the shell):
def function(command):
subprocess.run(command, shell = True, check = True)
I am aware that you can run cmd functions and commands directly with a shortcut, but I would like it to be controlled by Python.
I have little experience working with Windows shorcuts, so the best I can do is show you the following:
This is what I imagine it would like like.
After a quick Google search, the only help I can find is how to make a shortcut with Python, not how to run a function from it. So hopefully what I am asking is even possible?
Generally speaking AFAIK, you can't do it, however it could be done if the target script is written a certain way and is passed the name of the function to run as an argument. You could even add arguments to be passed to the function by listing them following its name in the shortcut.
The target script has to be set up with an if __name__ == '__main__': section similar to what is shown below which executes the named function it is passed as a command line argument. The input() call at the end is there just to make the console window stay open so what is printed can be seen.
target_script.py:
def func1():
print('func1() running')
def func2():
print('func2() running')
if __name__ == '__main__':
from pathlib import Path
import sys
print('In module', Path(__file__).name)
funcname = sys.argv[1]
vars()[funcname]() # Call named function.
input('\npress Enter key to continue...')
To make use of it you would need to create a shortcut with a Target: set to something like:
python D:\path_to_directory\target_script.py func1
Output:
In module target_script.py
func1() running
press Enter key to continue...
Generalizing
It would also be possible to write a script that could be applied to other scripts that weren't written like target_script.
run_func_in_module.py:
import importlib.util
from pathlib import Path
import sys
mod_filepath = Path(sys.argv[1])
funcname = sys.argv[2]
# Import the module.
spec = importlib.util.spec_from_file_location(mod_filepath.stem, mod_filepath)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
# Call the specified function in the module.
mod_func = getattr(module, funcname)
mod_func()
To make use of this version you would need to create a shortcut with a Target: set to something like:
python D:\path_to_directory\run_func_in_module.py D:\another_directory\target_script.py func2
Note that the target_script.py would no longer need the if __name__ == '__main__': section at the end (although having one would do no harm).
I have a Python script which is returning data by printing them, a function is not used.
I now want to make a function out of the script which works in the same way, but instead of printing the data, it should be returned by the app function.
Of course I could do it manually by writing "def myapp():", making all the indentations, and call it in the last line of the script, but I wonder if there is a tool for that?
Always write your script as one or more functions ending in two "magic" lines. A suitable template is
import sys # if you want a system return code
MY_CONSTANT = "whatever" # a symbolic constant
def a_function( args): # replace with your useful stuff
pass
# def b_function( args): # as many more defs as are useful
# can refer to / use both a_function (above) and c_function (below)
# def c_function()
# etc
def main():
print( "Script starting ...")
# parse arguments, if any parsing needed
# do stuff using the functions defined above
# print output, if needed
print( "End of script")
sys.exit(0) # 0 is Linux success, or other value for $? on exit
# "magic" that executes script_main only if invoked as a script
if __name__ == "__main__": # are we being invoked directly from command line?
main() # if so, run this file as a script.
Why? This file (myfile.py) is also usable as an import, at the interpreter prompt or in another file / script / module. It will define the constants and functions but it will not actually run anything when being imported as below. Either
import myfile
so you can refer to myfile.a_function, myfile.MY_CONSTANT, etc.
Or
from myfile import a_function
and then you can invoke a_function(args) without needing the prefix. You'll often see test or some random name: main() is not special.
I have a python script which is executed in Jython under Apache Pig. It defines some functions with the #schemaFunction resp. the #outputSchemaFunction decorator.
I want to test theses function with a standalone python main script outside Pig just under a "normal local Python interpreter. However when I run the script under a local Python system, the interpreter complains: "NameError: name 'outputSchema' is not defined" I understand that the standalone Python obviously does not support these decorators.
How can I test my script in a local Python interpreter? Can I somehow define the decorators in the calling script as "empty"? Or is there something like a command line option to ignore decorators?
I'm using pig 0.10.0.
When the module is used by pig as a UDF it sets __name__ to __lib__. Normally, __name__ is set to the actual name of the module (minus the .py). Therefore, you can define some empty decorators for outputSchema and outputSchemaFunction inside of an if block. Something like:
myudfs.py
#!/usr/bin/python
if __name__ != '__lib__':
def outputSchema(dont_care):
def wrapper(func):
def inner(*args, **kwargs):
return func(*args, **kwargs)
return inner
return wrapper
# Your UDFs go here
You can verify this yourself by putting print __name__ at the top of the myudfs.py.
This question already has answers here:
Why doesn't the main() function run when I start a Python script? Where does the script start running (what is its entry point)?
(5 answers)
Closed 5 months ago.
Consider:
#! /usr/bin/python
def main():
print("boo")
This code does nothing when I try to run it in Python 3.3. No error or anything.
What’s wrong?
gvim script
chmod 775 script
./script
You still have to call the function.
def main(): # declaring a function just declares it - the code doesn't run
print("boo")
main() # here we call the function
I assumed you wanted to call the print function when the script was executed from the command line.
In Python you can figure out if the script containing a piece of code is the same as the script which was launched initially by checking the __name__ variable against __main__.
#! /usr/bin/python
if __name__ == '__main__':
print("boo")
With just these lines of code:
def main():
print("boo")
you're defining a function and not actually invoking it. To invoke the function main(), you need to call it like this:
main()
You need to call that function. Update the script to:
#! /usr/bin/python
def main():
print("boo")
# Call it
main()
In Python, if you want to write a script to perform a series of small tasks sequentially, then there is absolutely no need to write a function to contain them.
Just put each on a line on its own; or use an expression delimiter like ; (not really recommended, but you can do is you so desire), likewise:
task1
task2
task3
task4
or
task1; task2; task3; (again **not** really recommended, and certainly not pythonic)
In your case your code could be turned to something like:
print('boo')
print('boo2')
print('boo3')
and it would still act as you expect it to, without the main() method, as they get evaluated sequentially.
Please note that the reason you might want to create a function for these series of tasks is:
to present a nice interface (to clients of the code),
or to encapsulate repeated logic
There might be more uses, but that's the first I can come up with, and serve to prove my point.
Now, if you feel compelled to write code that resembles the main() method in other programming languages, then please use the following Python idiom (as stated by other users so far):
if __name__ == '__main__':
doSomething()
The above is working as follows:
When you import a Python module, it gets a string (usually, the name under which it was imported) assigned as its __name__ attribute.
When you execute a script directly (by invoking the Python vm and passing it the script's name as an argument), the __name__ attribute is set to __main__
So when you use the above idiom, you can both use the script as a pluggable module by importing it at will, or just execute it directly to have the series of expressions under the if __name__ == '__main__': be evaluated directly.
Should you feel the need to dig through more information, my sources were the following:
Python documentation: Modules
Python documentation: Executing modules as scripts
Python documentation: The data model (search for __name__)
If you find the other answers confusing or intimidating, here's a parable which should hopefully help. Look at the following Python program:
a = 34
When it runs, it does something: before exiting the script, Python learns that there is a variable a and that its value is the integer 34. It doesn't do anything with this information, but it's a complete program which does something. In order for it to produce some actual value, it needs to interact with its environment, though. What does it do with this value? It could create 34 directories, or ping the 34th server in your data center, or check the strength of the passwords of the newest 34 users in your database, or whatever; or just print something.
a = 34
print(a)
The following program is in some sense very similar to the first one.
def b():
a = 34
print(a)
When you run this program, it does something: Python now knows that there is a function named b, and that it doesn't take any arguments, and that it contains some syntactically valid Python code which will be run when some other code calls it, but it doesn't actually do anything with this code yet. In order to observe any value being produced by the code in the function, you have to actually call it:
b()
(As an aside, maybe also note that the local variable a inside the function declaration b is distinct from the global variable with the same name.)
I know this must be a super basic question, however, I have tried finding a simple answer throughout SO and cannot find one.
So my question is this: How can I execute a python script from the command line such that I can see print statements.
For example, say I have the file test.py:
def hello():
print "hello"
If I enter the interpreter, import test.py, and then call test.hello(), everything works fine. However, I want to be able to just run
python test.py
from the command line and have it print "hello" to the terminal.
How do I do this?
Thanks!
UPDATED:
Yes, sorry, my script is actually more like this:
def main():
hello()
def hello():
print "hello"
Do I still need to call main(), or is it automatically invoked?
Add at the end of the file:
if __name__ == '__main__':
hello()
Your print statement is enclosed in a function definition block. You would need to call the function in order for it to execute:
def hello():
print "hello"
if __name__ == '__main__':
hello()
Basically this is saying "if this file is the main file (has been called from the command line), then run this code."
You have to have the script actually call your method. Generally, you can do this with a if __name__ == "__main__": block.
Alternatively, you could use the -c argument to the interpreter to import and run your module explicitly from the cli, but that would require that the script be on your python path, and also would be bad style as you'd now have executing Python code outside the Python module.
As I understand it, your file just has the following lines:
def hello():
print "hello"
The definition is correct, but when do you "call" the function?
Your file should include a call to the hello() function:
def hello():
print "hello"
hello()
This way, the function is defined and called in a single file.
This is a very "script-like" approach... it works, but there must be a better way to do it