"Sourcing" python scripts with multiple defs - MAYA - python

So I've been doing a lot of research and couldn't find a proper answer. I'm quite new to python so sorry if this is a simple question.
So, basically, I'm creating an UI that has a button that should call a function from another .py file. What I did so far is append the file's folder to sys.path and import the .py file as something else. Example, let's say I'm importing myTools.py:
import myTools as mt
Now I can successfully access all functions within myTools via mt.mainFunction() or anything with the mt. prefix.
Now my question:
When I run mt.myFunction() directly it works just fine. Problem is that mainFunction() is another UI that calls different functions at different times. All these functions are on the myTools file.. but Maya won't find them because when they are called within the mainFunction() they don't have the mt prefix.
I mean, I could run those defs on the userSetup.py but it's quite a big code and I wanted to do that the cleanest way :)
Any ideas?
Thanks in advance!
EDIT:
So I just realized is only one function that isn't working. I'm getting this error:
# Error: NameError: file <maya console> line 1: name 'annotationToLocator' is not defined #
Because of that error, I thought that my mainfunction couldn't find any other function on the module.
The actual code where I declare this function:
jobNum = cmds.scriptJob(e=['SelectionChanged', 'annotationToLocator()'])
def annotationToLocator ():
selList = cmds.ls(sl=True)
for item in selList:
if '_ANN' in str(item):
cmds.select(item,d=True)
newItem = str(item).replace('_ANN', '_LOC')
cmds.select(newItem,add=True)
A couple of weird things about this:
1) It works perfectly when I run the code directly.
2) I'm importing the module on the userSetup file.. I'm getting the error above not only when I try to actually run the function that calls this one, but also when Maya starts..
I tried commenting the scriptjob line and now it works just fine, although obviously now I don't have the scriptjob running. I think is some issue with modules and scriptjobs?!
I'm sorry, I know I got off of the original question path here! :)

This sounds like typical python behaviour and should work correctly. Each module has it's own global scope and each function defined in that module will have access to everything defined in that scope.
So in the myTools module each function has access to each other by name, and every function defined in your main module will have access to the mt module object and can get the functions as it's attributes.

You problem stems from using string references to your function. While that works, it only works if they function you're calling by string is in the global python scope -- which usually means it only works in the listener.
The better way to do any maya callbacks is by passing the functions directly to the callback as function objects, not as strings:
import mymodule
cmds.scriptJob(e=('somethingSelected', mymodule.fancyfunction))
Note that mymodule.fancyfunction is passed without parens: you are telling Maya "use this function." If you did it as mymodule.fancyfunction() you'd be telling Maya to use the result of a call to the function , not the function itself.

Related

calling a function defined in different python script within working folder

I am trying to call a function defined in file lidar_source_code.py from my main script py_lidar_depressions.py. There are numerous sources which explain how to do this such as this one, however When I attempt this the error ModuleNotFoundError: No module named 'lidar_source_code' is returned. I must say that I am not surprised at this error as at no point did I point to where the file is located even though relevant tutorials do not seem to suggest the need to. The code to import the file and all of the defined functions was as simple as the following.
from lidar_source_code import *
Is there something I am missing here. Am I correct that one must first define the path of the function containing file before importing it?
Thanks

Importing a function in one ipynb into the same ipynb (when called from elsewhere)

There are a tonne of Q&As on importing the contents of one .ipynb into another.
NOTE! This is not one of them!
The different methods are in various states of repair. The fact that there are so many answers and solutions is telling in itself :\ The one I got to work was:
## NOTE! If this fails, try switching and/or restarting kernels!
from importnb import Notebook
with Notebook(only_defs=True):
import other_notebook
Now I call the first function,
result = other_notebook.func_a()
Now I call another function, func_b, which relies on func_c in other_notebook,
result2 = other_notebook.func_b()
This throws a NameError,
NameError: name 'func_c' is not defined.
Of course it's there, in other_notebook, because when I call func_b from within other_notebook it's in scope and executes just fine.
Please help!
I am of course open to other ideas on a robust and current way to achieve the same thing.....

Reference a Python file in another Python file

I have two Python files, global.py and test_train.py, both sitting in the same folder. I am trying to allow test_train.py to access everything (functions, variables, etc. in global.py). I cannot get it to work. In the same folder is init.py. I have tried import global and have also referenced Source a Python's file from another Python file, but nothing seems to work. Suggestions?
You should change your file (global.py) name, when you import global.py,
the module name global will conflict with python keyword global
import global # global is keyword in python, you should avoid using this name
# so it will occur error
import global_test # this line is OK, if your .py name is global_test
Typically import global should work.
However, if it doesn't work, you should do a check to see if the import is happening successfully.
A print statement at the end of the global.py script should suffice to tell you so.
Otherwise, if the import is working, then you should try changing your code by encapsulating the entire contents of the global.py in a class, and then creating an object of that class in your test_train.py script to call its functions and attributes.
You can also make use of getattr function to call directly from global.py

Nested function causing troubles

I've got a Python script.
I've had several functions in this script which I decided to move to a 'package' folder beside the main script.
In this folder, I created a *.py file where I put all my functions.
I've placed an empty init.py near this file within the 'package' folder.
When starting the code of my main script with:
from package_folder.my_functions import *
the script works well when calling every functions from that file.
But when trying to import it directly:
import package_folder.my_functions
it doesn't seems to work as well as with the above technique.
The cause seems to be the fact that in the file wellmy_functions.py, I have a function that needs an other one, declared previously in that file.
I had this obscure error on that function that needs an other one:
TypeError: 'NoneType' object is not callable
Is this permissible and if not, how to manage this case?
It's generally not a good idea to use from module import *. Wildcard importing leads to namespace pollution; you imported more names than you need and if you accidentally refer to an imported name you may not get the NameError you wanted.
Also, if a future version of the library added additional names, you could end up masking other names, leading to strange bugs still:
Example
from my_mod1 import func1
from my_mod2 import *
If you upgrade my_mod2 and it now includes a my_mod2.func1 it'll replace the my_mod1.func1 import in the 1st line.

python NameError: name '<anything>' is not defined (but it is!)

Note: Solved. It turned out that I was importing a previous version of the same module.
It is easy to find similar topics on StackOverflow, where someone ran into a NameError. But most of the questions deal with specific modules and the solution is often to update the module.
In my case, I am trying to import a function from a module that I wrote myself. The module is named InfraPy, and it is definitely on sys.path. One particular function (called listToText) in InfraPy returns a NameError, but only when I try to import it into another script. Inside InfraPy, under if __name__=='__main__':, the listToText function works just fine. From InfraPy I can import other functions with no problems. Including from InfraPy import * in my script does not return any errors until I try to use the listToText function.
How can this occur?
How can importing one particular function return a NameError, while importing all the other functions in the same module works fine?
Using python 2.6 on MacOSX 10.6, also encountered the same error running the script on Windows 7, using IronPython 2.6 for .NET 4.0
Thanks.
If there are other details you think would be helpful in solving this, I'd be happy to provide them.
As requested, here is the function definition inside of InfraPy:
def listToText(inputList, folder=None, outputName='list.txt'):
'''
Creates a text file from a list (with each list item on a separate line). May be placed in any given folder, but will otherwise be created in the working directory of the python interpreter.
'''
fname = outputName
if folder != None:
fname = folder+'/'+fname
f = open(fname, 'w')
for file in inputList:
f.write(file+'\n')
f.close()
This function is defined above and outside of if __name__=='__main__':
I've tried moving InfraPy around in relation to the script. The most baffling situation is that when InfraPy is in the same folder as the script, and I import using from InfraPy import listToText, I receive this error: NameError: name listToText is not defined. Again, the other functions import fine, they are all defined outside of if __name__=='__main__': in InfraPy.
This could happen if the module has __all__ defined
Alternatively there could be another version of the module in your path that is getting imported instead of the one you are expecting
Is the NameError about listToText or is it something inside the function causing the exception?
In addition the __all__ variable gnibbler mentioned you could also have a problem with a InfraPy.pyc file lying around somewhere.
I'd recommend putting a import pdb;pdb.set_trace() first in the InfraPy.py file to make sure you are in the right file, and step through the definition of InfraPy.py to see what is happening. If you don't get a breakpoint, you are importing another file than you think.
You can also dir(InfraPy) after importing it, and check which file you are actually importing with InfraPy.__file__.
Can't think of any more import debugging hints right now. ;-)

Categories

Resources