I am calling a method within another. and the error for this script i am getting is
NameError: name 'mnDialog' is not defined
Is there a reason for it? I think it has something to do with executing a command which isn't on the global level. (i didn't have the impression that python has a global and local variable declaration.) What is the right syntax or the go around this?
thank you for your time.
import maya.cmds as cmds
def mnProgRun():
def mnDialog(*args):
cmds.confirmDialog( title='Confirm', message='Are you sure?',button=['Yes','No'], defaultButton='Yes',cancelButton='No',dismissString='No' )
def mnMakeWin():
cmds.window( 'mnWin', title = 'testman', wh=(260,100))
cmds.columnLayout(adjustableColumn=False, columnAlign='center')
cmds.button( label="Yes,it works",align='center',width=120,height=25, backgroundColor=[0.5,1,0.5],command='cmds.scriptJob( event=["SelectionChanged","mnDialog"])')
cmds.button( label="No, Thank You!",align='center',width=120,height=25, backgroundColor=[1,0.5,0.5],command='cmds.deleteUI("mnWin")')
cmds.showWindow( 'mnWin' )
mnMakeWin()
mnProgRun()
The problem is that the mnDialog is not being looked up from mnMakeWin, you are passing the name and it gets looked up later when you are not in the correct scope.
It may work to pass the function in instead of the name. I don't have maya installed, so I can't try it.
Otherwise you'll have to define mnDialog in the global scope which seems like an odd restriction to me
mnDialog is a local variable in mnProgRun. It is not accessible outside the function scope. If you want it to be, define it at the appropriate scope.
(i didn't have the impression that python has a global and local variable declaration.)
You have the wrong impression.
You should define mnDialog at the top level. It is not in the correct namespace.
Also, it's (almost) always unnecessarily complicating to nest functions in Python.
maya always have problems with scoops,
you may define mnDialog() and mnMakeWin() outside the function, at the top scoop level,
its maya problem not from python, as i faced problem when calling class methods from maya ui command (ex button event).
hope that will help you :)
##edit
import maya.cmds as cmds
def mnDialog(*args):
cmds.confirmDialog( title='Confirm', message='Are you sure?',button=['Yes','No'],
defaultButton='Yes',cancelButton='No',dismissString='No' )
def mnMakeWin():
cmds.window( 'mnWin', title = 'testman', wh=(260,100))
cmds.columnLayout(adjustableColumn=False, columnAlign='center')
cmds.button( label="Yes,it works",align='center',width=120,height=25,
backgroundColor=[0.5,1,0.5],command='cmds.scriptJob( event=
["SelectionChanged","mnDialog"])')
cmds.button( label="No, Thank You!",align='center',width=120,height=25,
backgroundColor=[1,0.5,0.5],command='cmds.deleteUI("mnWin")')
cmds.showWindow( 'mnWin' )
def mnProgRun():
mnMakeWin()
#run
mnProgRun()
Related
I am new to using the python interactive window and I like it but it seems to clear local variables in between runs, so if I run something like
def main():
dates = '2012152'
# %%
print(dates) # want to just run this
# %%
if __name__ == '__main__':
main()
# or even
main()
all at once it works fine but then if I just run the middle cell I get "dates not defined" error. It works outside of the function because apparently a global variable is saved:
dates = '2012152'
# %%
print(dates) # this works if this cell is run
# %%
Is there any way to get a similar behavior inside a function? If not it doesn't seem useful to me at all (maybe I have designed my code badly?).
Cells are a great way to experiment with flat code, but they are limited when working nested inside functions.
One way to work around this is to use a regular built-in python debugger and set a breakpoint within the function.
Here is a process I use for experimenting with code inside a function:
Set a breakpoint in the function, after the code you want to experiment with and start debugging.
Make any necessary changes to the code.
Select the lines that you've changed and that you want to run again. Make sure to include all the indentations as well.
Right-click and select Evaluate in Debug Console.
This will allow you to run the code one line at a time, see results, and make any necessary adjustments as you go along.
The process could be further improved by binding a keyboard shortcut to the this command.
Yes, print(dates) will not run as the dates variable isn't in scope, unless the function main is called and even then dates will be only in the local scope of the function, not in global scope.
So to print it outside the function, you need to first define it.
When I run the below code my websites or steam still open. Shouldn't I need to state print(link) or print(steam) for them to open?
import os
import webbrowser
import subprocess
import random
urls = ['https://www.ft.com/',
'https://www.youtube.com/watch?v=xvqcFcfhUVQ',
'https://roadmap.sh/backend',
'https://www.youtube.com/watch?v=YYXdXT2l-Gg&list=PL-osiE80TeTskrapNbzXhwoFUiLCjGgY7']
foxpath = 'C:/Program Files/Mozilla Firefox/Firefox.exe %s'
link = webbrowser.get(foxpath).open(random.choice(urls))
steam = subprocess.call(['C:/Program Files (x86)/Steam/Steam.exe'])
Why does this happen?
I eventually want to run the program from a function call, like below.
def wildcard():
print(random.choice(link, steam))
wildcard()
No, there is nothing special about print. print is just a function that takes in some value and displays it to the user.
If you had instead steam = 3 * 4, would you be surprised to learn that the value 12 is computed, and steam becomes a name for that value, even if you don't do anything with it? It's the same thing here - calling subprocess.call causes the program to launch, and it has nothing to do with the name steam, nor anything that you do or don't do with that name subsequently.
If you were to add the print(steam) line that you have in mind, what it would display (after you close steam and control returns to your program) is the "return code" of that program - this gets into the details of how your operating system works, but most likely it would be something like 0.
If you want something that you can later call in order to launch Steam - well, that's a function. Like you already know how to do:
def steam():
subprocess.call(['C:/Program Files (x86)/Steam/Steam.exe'])
As soon as you issue webbrowser.get or subprocess.call, they execute. Your variables are really storing the return values of those functions, not aliases to those function calls.
If you want to alias the function calls as it appears you are intending, you could do something like this:
def open_link():
return webbrowser.get(foxpath).open(random.choice(urls))
def open_steam():
return subprocess.call(['C:/Program Files (x86)/Steam/Steam.exe'])
Then your top level would be:
def wildcard():
random.choice([link, steam])()
wildcard()
Note the syntax difference for choosing the functions randomly. See this answer for more clarification.
You do invoke something:
steam = subprocess.call(['C:/Program Files (x86)/Steam/Steam.exe'])
The documentation for subprocess.call is clear on what the call method does: it invokes the given argument as a subprocess.
The problem is that your code isn't inside a function, so, when you execute it, it runs all the diretives including
steam = subprocess.call(['C:/Program Files (x86)/Steam/Steam.exe'])
Which calls C:/Program Files (x86)/Steam/Steam.exe, opening your steam app.
Hope it helps.
Thank you, I understand now. I actually just resolved the problem with the following
def wildcard():
for x in range(1):
rand = random.randint(1, 10)
if rand > 5:
link = webbrowser.get(foxpath).open(random.choice(urls))
else:
subprocess.call(['C:/Program Files (x86)/Steam/Steam.exe'])
wildcard()
I have a tool I wrote in python that works completely fine when running in the maya script editor. However, I want to be able to import the script from the script directory. Which should be simple, and I am shocked I can't find the solution while searching the web.
My script format is like this example:
import maya.cmds as cmds
# GUI code with buttons, they call the functions below.
#
#
def function1():
#commands that do things
def function2():
#commands that do things
#List of functions continues
Like I said, the program functions perfectly when run in the script editor. When saving the script to the directory and using this method:
import module
reload (module)
module.function()
The GUI loads fine, but then when pushing the gui buttons, it says the functions are not defined. I don't understand what I am missing? If the script was loaded, shouldn't the functions be defined? Any help would be greatly appreciated, thank you!
Just because the GUI loads doesn't mean that all of your functions loaded properly. You need to put your file, (module.py) in a directory that is visible to your PYTHONPATH. If you're in Maya, you can also put it in the MAYA_SCRIPT_PATH
The PYTHONPATH / MAYA_SCRIPT_PATH are environment variables that you set before launching Maya. In a default Maya installation, some places where you could put your module.py file would be:
(Windows) C:\Users\YOUR_USER_NAME\Documents\maya\scripts
(Linux) ~/maya/scripts
(Mac) - Not sure, put probably also ~/maya/scripts
If you want to know where else you can place it, you run this
import os
print(os.getenv('MAYA_SCRIPT_PATH', ''))
print(os.getenv('PYTHONPATH', ''))
Any location in that list that you have write permissions to is OK to add your module.py file.
Also, it's worth noting that in your example module.function() would fail. It'd need to be module.function1() or module.function2() but I assume you know that. Hope this helps
Sup guys
So i know this is an old question that has already been answered but I have some extra information that helps in regards to GUI functions not working. (same error)
and there's basically nothing on this anywhere.
so the script director only helps when loading in the module through the shelf but will still return the same error "fuction is not defined"
this has todo with how the function is called through the UI element.
example.
this is will allow you to call function in the script editor
but gives you the function not defined error when the module is imported
def GUI_function():
pm.button( command = "function()")
def function():
do stuff
this on the other hand works.
def GUI_function():
pm.button( command = function)
def function(*_):
do stuff
i don't know why but maya tends to think function() is a nodetype
so remove the brackets if you not using arguments and you good to go
I am creating a rig through scripting and I have a UI. I would like to connect multiple functions to one button. Or rather, have a function inside of a function. Any suggestions on how to go about this issue?
I am importing the following libraries:
import maya.cmds as cmds
from functools import partial
Could you explain further more what you to do with a little example ?
I see you want to use partial so you may have multiple variables to pass through ?
My first idea would to create a function grouping your multiples function, ie :
def temp01():
return cmds.ls(sl=True)
def connection(obj01, obj02):
someCommand(obj01, obj02)
def printor():
print('yeah it is working')
def uiCommandButton_whatShouldIDoFunc(obj02, specialOkay, *args):
someCommand(temp01(), obj02)
specialOkay() #should print message
button01 = cmds.button(c=partial( uiCommandButton_whatShouldIDoFunc, cmds.ls(sl=1)[-1]), printor )
To have things nice and clean, I would use handlers.
A handler is a method that is called when an event occurs on your GUI element, like click. In the handler you can do whatever you want to (like calling your two functions). Handlers/event handlers are a tried and test GUI programming technique.
Here is an example:
my_button = cmds.button(command=partial(my_button_on_click_handler, arg1, arg2))
def my_button_on_click_handler(arg1, arg2):
# call all your functions and do stuff here
my_other_func1(arg1)
my_other_func2(arg2)
Some great posts on this topic (courtesy: #theodox and his awesome blog):
http://techartsurvival.blogspot.ca/2014/04/maya-callbacks-cheat-sheet.html?m=1
http://techartsurvival.blogspot.ca/2014/04/the-main-event-event-oriented.html?m=1
There is a "dirty" way of doing so by using PyMel and PySide/Qt.
First, turn your button into Pymel button :
import pymel.core as pm
import pymel.core.uitypes as pui
pyBtn = pm.button(label="", etc...)
or
pyBtn = pui.PyUI(my_button)
Then, convert it to a QtObject:
qtBtn = pyBtn.asQtObject()
And finally, you can add functions when the button is clicked like that:
qtBtn.clicked.connect(func1)
qtBtn.clicked.connect(partial(func2, arg1))
etc...
But like I said, this is not really recommended... It's just another way of doing it.
I thought it might be interesting to share it.
As an example, you can use this solution if the UI already exists, but you can't access the code that creates it.
Otherwise, I would do like suggested in the other answers, creating handlers functions.
PS : This will only works with maya2014 and above, or a maya with PyQt installed !
I'm creating a python bridge to a program. I'm using the pipi daemon module to prevent lockups.
http://pypi.python.org/pypi/python-daemon/
I basically want to eventually put this in a module for easy reuse and to build a python wrapper.
In testing, if I put the daemon context inside a function it won't work.
If I put it outside the function, it works flawlessly.
def createCube():
prog('create cube/params')
def runFunc(func):
with daemon.DaemonContext():
prog = createConnection().command #our port connection system
func()
sys.exit()
runFunc(createCube)
I can't think of a reason why it wouldn't work inside a function when it works fine outside of it, unless it's looking for a namespace perchance?
Any help would be appreciated. Thank you very much!