Python scripts running twice when clicked inside Maya

Anyone knows an issue like this?

Basically you click a button in the shell, and if I remember correctly sometimes even by selecting the shell button code and pressing numpad enter, causes the script to run twice.

I wonder if anyone dealt with this already.

Thanks,
Light

… o.O. Script editor open, and print statements are flooding the log, forcing redraw? The only behavior I have seen like you are describing, is associated with prints. Guarding print statements with a “verbose” condition has given back performance to me, and makes the log cleaner for our artists. If the button code doesn’t have the script editor visible, this may explain the difference, but if you get problems when just calling the proc, without the script log open, then I really don’t know. Do you have a code sample that exhibits this behavior that we can see?

Thanks Lithium. Something like:

import time
from datetime import datetime

print “sec: %s” % datetime.now().second

time.sleep ( 5 )

in a file and then:

import filename
reload (filename)

as a shelf button. Sometimes runs twice. Here I used the print to show it clearly. In the real case, I have a directory picker and after the script is done, the dialog reappears (for the 2nd execution). I was suspicious about windows registering the click twice.

Actually I didn’t get this to print twice but the 3 other scripts that I use runs twice and they are very different. Last one is for Photoshop which just creates a new doc, etc, but sometimes it creates 2 at once.

Cheers,
Light

Oh, I am a moron, I thought you meant running /twice as long/. For just running twice, your python script is set up like a macro. I’m on a mobile phone right now, so I can’t type code but if you google for ‘if name == “main”:’ you should find examples of how to set up your python scripts.

Hey thanks for taking the time to write it on your phone, I will try it now (:

EDIT: Btw I just read about it and I am not sure if it would fix it. Basically in the original code file, I have a bunch of methods and then some code that calls the already defined methods. I assumed the python interpreter would just execute these statements and then call the required methods. Do you think the if name == “main”: would change the result?

Thanks again,
Light

Just out of curiousity, why are you doing a reload after your import?

Hi Seth,

Actually I am not sure (: This is the workflow shown to me by the Maya experts here, so I took it for granted. You think this might cause the issue? I just remember being told that this ensures that the script is recompiled and reloaded, so you don’t use the old version.

Cheers,
Light

I do this when I’m building a script. It allows me to open Maya and just click a button to load it. And if I make any changes I can use the same button. I suppose it’s not really a big deal. You could just run the import and reload from the script editor.

I forgot to mention that I use an external editor but don’t do “live executions”. I just edit the script and just click the button inside Maya like Brandon.

Thanks,
Light

[QUOTE=Bharris;3178]I do this when I’m building a script. It allows me to open Maya and just click a button to load it. And if I make any changes I can use the same button. I suppose it’s not really a big deal. You could just run the import and reload from the script editor.[/QUOTE]

Granted, but if you’re not wrapping your code in a def, how do you get it to reload without triggering the contents of the file? you could always do a:

import filename
reload(filename)
execfile(filename.file)

which would give you benefit of being able to throw in the if name==“main” clause, but that seems kinda hacky…altho if for some reason you can’t wrap your script code in a def it seems like that’s the way to go, in which case your script would be (using the earlier example):


import time
from datetime import datetime
if __name__=="__main__":
print "sec: %s" % datetime.now().second
time.sleep ( 5 )

Hopefully someone has a better solution that i’m overlooking…

Super apologies for how rough this is going to be, still mobile.


def foo():
  print "inner function: do this."

print "macro: don't do this."

if __name__ == "__main__":
  print "main : only called when run directly"
  foo()

Then in maya:


import fooFile
reload fooFile #optional
fooFile.foo()

Does this make sense?

DJ. yes I usually have all of my scripts within defs.

example of one of my tool buttons

import bhAuto
reload(bhAuto)
bhAuto.bhRigWindow()

Right, but the example Light gave didn’t have a def.:wink: I’m not sure if that’s specific to what he’s doing, but i’m just giving some solutions in the context of the problem he’s presenting…

…you know another thing you could try (Light) is doing all your imports in userSetup.py then your shelf would only have to throw a reload…

Disclaimer: Lith is nuts and you shouldn’t really listen to anything he has to say

<Rant>
In my personal opinion, everything should be guarded behind a def, class, or if__main__. if__main__'s should be only for command-line runs of the modules. Public and Private ( “__foo” ) should be used in modules to expose relevant members and pydocs should be leveraged to make everything clear. A convention can be used to make finding a base function easier, but to call a function you must know what function you are calling. execfile’s should be eschewed except in cases of dynamically-generated code, and if doing that, you should have a very good reason.
</Rant>

and to support my execfile vendetta:
Foo.py


def Foo():
    print "foo"

if __name__ == "__main__":
    Foo()

Bar.py


def Bar():
    print "bar"

if __name__ == "__main__":
    Bar()
    execfile( "Foo.py" )
    Foo()                   #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Also, dynamic reloading is a very nasty problem. If you control your Maya environment, you could set up a Rollback Importer. Which is a neat bit of code that resets your modules. You would do something like:

[ul]
[li]Create RollbackImporter Singleton at startup.
[/li][li]Import as usual.
[/li][li]Call uninstall on the RollbackImporter when you need to refresh.
[/li][li]Import like brand new!
[/li][/ul]

What I don’t know is how well that works with “from [module] import [def]”. Our development needs are not yet great enough that we’ve wanted to tangle with something like a Rollback Importer. I wish the python peoples would make some sort of built-in with the same functionality though. I start to feel really bad when you start messing with python internals.

Cheers! -Lith

PS: apologies to grammar nazis for my “oh shit here comes an s! use of apostrophes”

[QUOTE=Lithium;3184]
<Rant>
In my personal opinion, everything should be guarded behind a def, class, or if__main__. [/QUOTE]

Totally agree, names and their spaces are your friends. Also, agree that the illustrated use of execfile is all kinds of wrong:D: execfile does have its place, the main problem i’ve seen with its use is when people try and use it to a) avoid having to manage/be aware of their dependencies (which in my opinion is just lazy on the part of any coder) and b) see a) (seriously, this is part of mine own personal execfile vendetta, hehe:curses:)

Thanks guys. Yeah I generally do it like that unless it’s a framework, so like:

<specific defs>

<some statements>

Lithium: I can try your example in #11, but I think it would still be called twice, ie: the foo method.

Seth: it’s a good idea to import them in userSetup.py. I didn’t think of it. Do you know if there are any drawbacks in importing all scripts in the mydocuments/maya/scripts dir so you don’t have to add new import statements everytime you add a new script there?

Lithium, as for what you said in your last post, I totally agree, it’s a good idea to do that. I didn’t know about the main thing but I can see it’s usefulness.

I will post more when I have more info on the issue I am having. This guy seems to have a similar issue I think.

Cheers,
Light

First I rarely use execFile unless it is a shelf button that needs to call a specific script.

here is how I handle a lot of my scripts…



import myFile as myF

def main ():
    lvar = myF.procedure(*args)
    print lvar


def showError (msg):
    PopupError(msg)
    
if __name__ == '__main__':
    try:
        main() #main function
    except Exception, inst:
        showError('EPIC FAIL: Script failed with an internal error (%s)  See the Script Editor for details.' % (inst))
        raise