Calling python functions without running from the editor - python

Please excuse what I know is an incredibly basic question that I have nevertheless been unable to resolve on my own.
I'm trying to switch over my data analysis from Matlab to Python, and I'm struggling with something very basic: in Matlab, I write a function in the editor, and to use that function I simply call it from the command line, or within other functions. The function that I compose in the matlab editor is given a name at the function definition line, and it's generally best for the function name to match the .m file name to avoid confusion.
I don't understand how functions differ in Python, because I have not been successful translating the same approach there.
For instance, if I write a function in the Python editor (I'm using Python 2.7 and Spyder), simply saving the .py file and calling it by its name from the Python terminal does not work. I get a "function not defined" error. However, if I execute the function within Spyder's editor (using the "run file" button), not only does the code execute properly, from that point on the function is also call-able directly from the terminal.
So...what am I doing wrong? I fully appreciate that using Python isn't going to be identical to Matlab in every way, but it seems that what I'm trying to do isn't unreasonable. I simply want to be able to write functions and call them from the python command line, without having to run each and every one through the editor first. I'm sure my mistake here must be very simple, yet doing quite a lot of reading online hasn't led me to an answer.
Thanks for any information!

If you want to use functions defined in a particular file in Python you need to "import" that file first. This is similar to running the code in that file. Matlab doesn't require you to do this because it searches for files with a matching name and automagically reads in the code for you.
For example,
myFunction.py is a file containing
def myAdd(a, b):
return a + b
In order to access this function from the Python command line or another file I would type
from myFunction import myAdd
And then during this session I can type
myAdd(1, 2)
There are a couple of ways of using import, see here.

You need to a check for __main__ to your python script
def myFunction():
pass
if __name__ == "__main__":
myFunction()
then you can run your script from terminal like this
python myscript.py
Also if your function is in another file you need to import it
from myFunctions import myFunction
myFunction()

Python doesn't have MATLAB's "one function per file" limitation. You can have as many functions as you want in a given file, and all of them can be accessed from the command line or from other functions.
Python also doesn't follow MATLAB's practice of always automatically making every function it can find usable all the time, which tends to lead to function name collisions (two functions with the same name).
Instead, Python uses the concept of a "module". A module is just a file (your .py file). That file can have zero or more functions, zero or more variables, and zero or more classes. When you want to use something from that file, you just import it.
So say you have a file 'mystuff.py':
X = 1
Y = 2
def myfunc1(a, b):
do_something
def myfunc2(c, d):
do_something
And you want to use it, you can just type import mystuff. You can then access any of the variables or functions in mystuff. To call myfunc2, you can just do mystuff.myfunc2(z, w).
What basically happens is that when you type import mystuff, it just executes the code in the file, and makes all the variables that result available from mystuff.<varname>, where <varname> is the name of the variable. Unlike in MATLAB, Python functions are treated like any other variable, so they can be accessed just like any other variable. The same is true with classes.
There are other ways to import, too, such as from mystuff import myfunc.

You run python programs by running them with
python program.py

Related

putting inner python function at the bottom of the code

How can I put an inner python function at the bottom of the code, and call it from the beginning?
For example, VBA dosent care where the phisical inner function code is.
Rexx ( which is also interpreter) also does not care.
How can I do it in Python?
It is much easier to understand the code when the functions are at the bottom.
thanks
You could not do that.
Python runs your code from top to bottom, so it first needs to declare your functions to access them later. You can not first access, later declare, because you would tring to access non exsistent values.
In compiled code, it may works. But in script languages, like python, it does not. As far as I know.
You can do like this:
def main():
print(f(3))
def f(x):
return x * x
if __name__ == "__main__":
main()
Or do you talk about nested functions?
BTW: using the construct in the bottom of my example is anyway good practice to execute the main code only if the module is called as a script. And if it isn't, code shouldn't be extensively executed anyhow before the module is imported (and functions called from outside).

Python nameError help when importing from another file

I have a function in maya that imports in other functions and creates a shelf with buttons for specific functions. I have a function that has a scriptJob command that works fine. if I import that file in manually and not through the shelf button, but gives a NameError when using the shelf script to run it.
This is an example of the script
myShelf.py file:
import loopingFunction
loopingFunction.runThis()
loopingFunction.py file:
import maya.cmds as mc
def setSettings():
#have some settings set before running this
runThis()
def runThis():
print "yay this ran"
evalDeferred(mc.scriptJob(ro=True,ac=["'someMesh.outMesh',runThis"])
if I run this through the shelf function, I get a runThis nameError is not defined and if I try modifying the scriptJob command to loopingFunction.runThis, I get a nameError loopingFunction is not defined(not sure if using loopingFunction.runThis is even correct, to be honest)
Not sure how I can get around this without having to manually import in the function rather than through the shelf file.
Using string references for callback functions like this often leads to scope problems. (More on that, and why not to use strings, here)
If you pass the function directly to the callback as an object, instead of using a string, it should work correctly as along as you have actually imported the code.
in this case you want an evalDeferred -- do you actually need it? -- so it helps to add a little function around the actual code so that the scriptjob creation actually happens later -- otherwise it will get evaluated before the deferral is scheduled.
def runThis():
print "callback ran"
def do_scriptjob():
cmds.scriptJob(ro=True, ac=('someMesh.outMesh', runThis)
cmds.evalDeferred(do_scriptjob)
In both runThis and do_scriptjob I did not add the parens -- we are letting the evalDeferred and the scriptJob have the function objects to call when they are ready. Using the parens would pass the results of the functions which is not what you want here.
Incidentally it looks like you're trying to create a new copy of the scriptJob inside the scriptJob itself. It'd be better to just drop the runOnce flag and leave the scriptJob lying around -- if something in runThis actually affected the someMesh.outMesh attribute, your maya will go into an infinite loop. I did not change the structure in my example, but I would not recommend writing this kind of self-replicating code if you can possibly avoid it.
You have a problem of nested/maya scope variables
mc.scriptJob(ro=True,ac=["'someMesh.outMesh',runThis"]
This line is a maya command string that is evaluated in the main maya scope (like a global)
As your function have a namespace with the import : 'loopingFunction', you need to enforce it in the string command.
import loopingFunction
loopingFunction.runThis()
You should write
evalDeferred(mc.scriptJob(ro=True,ac=["'someMesh.outMesh',loopingFunction.runThis"])
If you want something more general, you can do :
def runThis(ns=''):
print "yay this ran"
if ns != '':
ns += '.'
evalDeferred(mc.scriptJob(ro=True,ac=["'someMesh.outMesh',{}runThis".format(ns)])
and then run in shelf :
import loopingFunction
loopingFunction.runThis('loopingFunction')
like this you can write any formof namepsaces :
import loopingFunction as loopF
loopF.runThis('loopF')

How to make a python module or function and use it while writing other programs?

There where many instances where I have to write large line of code over and over again in multiple programs. So I was wondering if I could write just one program, save it and then call it in different programs like a function or a module.
An elementary example: I write a program to check if a number is palindromic or not. Then I want to write a program to check if a number is palindromic and a prime, could I just call the first program and do the rest of the code to check if it is prime or not?
It is about writing reusable code. I can suggest you to write reusable code in specific function in separate python file and import that file and function too.
For example you need function called sum in other function called "bodmas" then write function called sum in one python file say suppose "allimports.py":
def sum(a,b):
return a+b
Now suppose your "bodmas" named function is some other python file then just import all the required functions and use is normally by calling it.
from allimports import sum
def bodmas:
print(sum(1,1))
One important thing is be specific while import your module as it will effect performance of your code when length of your code is long.
Suppose you want to use all functions then you can use two option like :
import allimports
print(allimports.sum(1,1))
other option is
from allimports import *
print(sum(1,1))
and for specific imports is as follows:
from allimports import sum
print(sum(1,1))
Yes. Let's say you're writing code in a file called palindrome.py. Then in another file, or in the python shell you want to use that code. You would type
import palindrome
either at the top of the file or just into the shell as a command. Then you can access functions you've written in palindrome.py with statements like
palindrome.is_palindrome('abba')
It's important to note that to do this propery, the code in palindrome.py must be in functions. If you're not sure how to do that, I recommend the official Python tutorial: https://docs.python.org/3/tutorial/index.html
it's easy to write a function in python.
first define a function is_palindromic,
def is_palindromic(num):
#some code here
return True
then define a function is_prime,
def is_prime(num):
#some code here
return True
at last, suppose you have a number 123321, you can call above function,
num = 123321
if is_palindromic(num):
if is_prime(num):
print 'this number is a prime!'
ps, maybe you could try to use some editors like vscode or sublime.

Passing a variable from Excel to Python with XLwings

I am trying write a simple user defined function in Python that I pass a value to from Excel via Xlwings. I ran across some examples with an Add-in that you need to import user defined functions, but that seems overly complex.
Why isn't my example working?
VBA:
Function Hello(name As String) As String
RunPython ("import Test; Test.sayhi(name)")
End Function
Python (Test.py):
from xlwings import Workbook, Range
def sayhi(name):
wb = Workbook.caller()
return 'Hello {}'.format(name)
Error:
NameError: name 'name' is not defined
Make sure you're supplying the argument correctly:
RunPython ("import Test; Test.sayhi('" & name & "')")
The text inside RunPython() should be a valid python script. So the comment from "Tim Williams" is a quick solution. You just need to be careful to avoid ' character inside the name variable to break the python script.
If you need to write UDF (User Defined Function) a lot, or need to pass in value to get the output and then handle the result via VBA, try use ExcelPython instead of Xlwings.
Note, ExcelPython and Xlwings can work together, you can have both without conflict.
I think it's better you play the example to understand the difference. My understanding is limited to my knowledge, which might not be correct.
To summarize the difference:
ExcelPython needs a installer to be installed, it is good in UDF, which helps if you want to pass arguments in and out, and the function is cached in memory, so later call will be very quick.
Xlwings is simpler by just add the VBA module, no installer needed. It trigger Python in the background each time to run the script (each call starts a new process), in the script you can manipulate (read/write) Excel via COM.
I have the same question in the beginning, but later I find out using VBA in Excel side (intellisense) plus ExcelPython on UDF (simply process and return the data back) is a nice combination, so I think ExcelPython is only what I need.
As mentioned earlier, the 2 components have no conflict, you can have both. If the 2 author agree too, it is a good idea to combine them.

main() function doesn't run when running script [duplicate]

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.)

Categories

Resources