Maya 2018 / Python - Import Module and Calling functions from cmds.button

I am currently trying to create an interface for a tool I made for Maya.
Here’s the process, problem happen at step 3/.

1/ Every user loads a module loadShelf.py from their userSetup.py


2/ loadShelf.py, which is on the server, creates a shelf. Every button on that shelf loads a different module.py

Exemple:
     def simmetrizeButton():
         import tool_symmetrize
         imp.reload(tool_symmetrize)
         tool_symmetrize.symmetrizeWindow()

        self.addButon("Symmetrize", icon="simmetry_32.png", command=simmetrizeButton)

Pressing the shelf button “Symmetrize” will import tool_symmetrize.py, reload tool_symmetrize.py and launch function tool_symmetrize.symmetrizeWindow().


3/ tool_symmetrize.symmetrizeWindow() will launch a tool with cmds.window. Buttons inside this window will launch function from tool_symmetrize.

Exemple: tool_symmetrize.py:
    def testA():
        print 'test A'

    cmds.window(....)
    cmd = "testA()"
    cmds.button('Launch Test A', command=cmd)
    cmds.showWindow(....)

The problem is that from a newly opened maya, after succesfully loading tool_symmetry.symmetrizeWindow() from the shelf, calling functions from tool_symmetry.py with the buttons won’t work:

Error: NameError: file line 1:name ‘tool_symmetrize’ is not defined

So… tool_symmetrize.py doesn’t seems to be loaded, but symmetrizeWindow() which works fine is loaded from this very module. I don’t understand.

I tried changing from step 3/ cmd = “testA()” to cmd = “tool_symmetrize.testA()”, but it does not work either.

Can someone help me? I don’t understand how a module clearly loaded by maya can’t be defined when a function from that module call a function from the module.

Thanks.

1 Like

First step – don’t use the string form of the command, it often results in this kind of confusion (see this link for a more detailed explanation why). You want to convert

cmd = "testA()"
cmds.button('Launch Test A', command=cmd)

to

import tool_symmetrize

#...
cmds.button('Launch Test A", cmd = tool_symmetrize)

that may still fail – but it should fail at import time (before the button is actually created) ; that’s a canary in the coalmine proving that tool_symmetrize.py is not available on the path. The string for hides that problem until the button is actually pressed , and often it will work for you because you’ve been testing on your own machine and then fail for others. Doing it by passing the functions directly helps you spot path related problems early

Thanks for your response Theodox.
It works as long as the function is written as
def XXX(*args):

Do you know how to pass an actual argument to the function from the button?

If you need pass arguments, the usual method is with a lambda

cmds.button(command=lambda *x: some_func(arg1, arg2, arg3='derp')

Thanks a lot, it really helped me.
I find cmds to be a real pain to create windows, I think I’m going to try Pyside2: http://zurbrigg.com/tutorials/pyside2-for-maya

@theodox might beat me to this, but for a more modern method of creating Maya guis, I would say take a look at a project he and I have been working on the last few years, https://github.com/theodox/mGui.

While I’m not against using one of the many Qt bindings, I do find they bring a lot of complexity to the party which is something to watch out for.

And if you are big on using a Qt-based library, I would recommend @marcuso’s excellent https://github.com/mottosso/Qt.py library, as it will help make anything you do be a bit more portable across versions.

Button calllbacks always have to handle a (useless) extra argument that maya passes. Other gui things (menus, I’m not sure about shelf buttons) also have extra arguments. It’s safe to ignore them if you don’t need them,

Bob’s answer is one of the two ways – they other is simply to use an inline function.

   def callback(*_):
         tool_symmetrize(arg1, arg2, arg3)

  cmds.button('label', c = callback)

Depending on style or complexity both work fine (the link in my first answer covers the differences).

The basics won’t actually change much – and Pyside / QT is a much more complex system with lots of opportunities to shoot yourself in the foot. I’d wait and learn it after you already are comfortable with cmds.

1 Like

I’ll definitly try mGui with my next tool.
PySide2 seems interesting as it’s a cross platform skill to learn, if I understood correctly, but I don’t really have time for “lots of opportunities to shoot yourself in the foot”… I’ll probably try it on a personnal project.

Hello,I have tried your the method you mentioned above ,but still got that error.Could you give me some tips how you figure it out ?

Hey
Can you describe what you are trying to do? Maybe post a snippet so that we can pinpoint the problem.