how to create a stack of scripts and execute them with Qt?

77 views
Skip to first unread message

Rudi Hammad

unread,
Dec 27, 2015, 4:49:02 AM12/27/15
to Python Programming for Autodesk Maya
Hello,
I have no idea how to do that. I have uploaded an image to explain it.
I want to create a stack of scripts and execute them in order. I want to be able to add and delete them dynamically , and even save a preset of the stack I made to be able to load it later for another character.
 I used the listWidget but I don´t think that works
Any guidance to know were should I start? Because right now I am lost.
thanks

stack.jpg

Marcus Ottosson

unread,
Dec 27, 2015, 6:47:00 AM12/27/15
to python_in...@googlegroups.com

In Python, importing a script is the same as running it.

To list a series of scripts, you can simply list the directory in which they lie, and then run them by importing them. You can programmatically import a module using __import__("hand script.py"). An alternative to importing is execfile which is similar, but doesn’t require that you expose a directory via sys.path first.

import os

for script in os.listdir("."):
  __import__(script)

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/e5cc06d4-59ae-4f2c-9bd2-8096f93c32c1%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Marcus Ottosson
konstr...@gmail.com

Rudi Hammad

unread,
Dec 27, 2015, 9:06:03 AM12/27/15
to Python Programming for Autodesk Maya
Hey marcus,
The idea is to do that but using a widget that lists scripts that you can add or remove in a UI.
What is the diference between __import__ and just import? Both excute the script right?
But importing doesn't work if the module have classes and methods. You should import the module, create a class object and then theClassobject.myMethod()
Am I right?
Anyway,back to the main question that was about adding scripts un the Ul

Rudi Hammad

unread,
Dec 27, 2015, 9:06:04 AM12/27/15
to Python Programming for Autodesk Maya

Justin Israel

unread,
Dec 27, 2015, 9:32:13 AM12/27/15
to Python Programming for Autodesk Maya


On Sun, 27 Dec 2015 6:06 AM Rudi Hammad <rudih...@gmail.com> wrote:
Hey marcus,
The idea is to do that but using a widget that lists scripts that you can add or remove in a UI.
What is the diference between __import__ and just import? Both excute the script right?

__import__ is the same as the import statement, but lets you do it more dynamically with names as strings that you know only later at runtime. But just like the normal import, if the module has already been imported, then importing it again will have no effect unless you reload it. 

But importing doesn't work if the module have classes and methods. You should import the module, create a class object and then theClassobject.myMethod()
Am I right?

You have to determine how these "scripts" will be structured to make them usable by your application. It is kind of like a plugin system. They are "scripts" if they are directly runnable. Though usually it's a bad idea to write python modules that execute purely by importing. Unless these scripts are only for your app, and no one else. 
Another way is to make them all define a consistent interface. You can require that an action module for your app define a specifically named function (or functions). Then you can import them and run the functions entry point to launch the action. 

Maybe like this... 

#---
ACTION_NAME = "My action" 

def run():
    print "running %r" % ACTION_NAME 
#---

You can use the imp module to do a lower level import which somewhat bypasses the sys.modules lookup and lets you repeatedly load source code :
https://docs.python.org/2/library/imp.html



Anyway,back to the main question that was about adding scripts un the Ul

That bit would be a matter of deciding where you require that action scripts be stored in the first place. Maybe you check a certain directory (like Marcus suggested). Maybe you look at an environment variable that people can set to change the action location or specify multiple ones, separated by a ":" 

Once you know your list of action modules, you can load them, read their description names and display them in your list, while associating them with the module that should be loaded. 


--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.

Marcus Ottosson

unread,
Dec 27, 2015, 10:41:50 AM12/27/15
to python_in...@googlegroups.com

I can’t tell if you are asking about how to visually append items to a list, as in your example, or whether you are asking about how to build a plug-in architecture?

I’ll assume you mean the latter as it is the more difficult aspect.

Importing multiple times as Justin said is a good point about many of the gotchas you might experience while working on this. It’s possible you might find similar problems with reloading a module and using execfile as well; for example imports taking place within your script are typically cached like any other import, which means you’ll need to somehow either keep track of those imports and make sure they happen once per script, or count on the fact that it may happen.
Depending on the nature of your scripts, a safe method of running each script in isolation, without worrying too much about side-effects or paths, might be to subprocess each invokation.

import os
import sys
import subprocess

for script in os.listdir("."
):
  subprocess.call([sys.executable, script])

At this point, no amount of nested imports, side-effects or messing about with PYTHONPATH can throw your execution mechanism off guard!

The next step might be to append each result of os.listdir to your GUI.

# Using QListWidget with QListWidgetItem

for script in os.listdir("."
):
  item = QtGui.QListWidgetItem(script)
  self.mylistwigdet.addItem(item)

Then, once hitting “run”, you would do as above; loop through each item and run each script.

for i in xrange(widget.count()):
    item = widget.item(i)
    script = item.text()
    subprocess.call([sys.executable, script])

That should do it!



For more options, visit https://groups.google.com/d/optout.



--
Marcus Ottosson
konstr...@gmail.com

Justin Israel

unread,
Dec 27, 2015, 10:59:27 AM12/27/15
to python_in...@googlegroups.com
On Mon, Dec 28, 2015 at 4:41 AM Marcus Ottosson <konstr...@gmail.com> wrote:

I can’t tell if you are asking about how to visually append items to a list, as in your example, or whether you are asking about how to build a plug-in architecture?

I’ll assume you mean the latter as it is the more difficult aspect.

Importing multiple times as Justin said is a good point about many of the gotchas you might experience while working on this. It’s possible you might find similar problems with reloading a module and using execfile as well; for example imports taking place within your script are typically cached like any other import, which means you’ll need to somehow either keep track of those imports and make sure they happen once per script, or count on the fact that it may happen.
Depending on the nature of your scripts, a safe method of running each script in isolation, without worrying too much about side-effects or paths, might be to subprocess each invokation.

import os
import sys
import subprocess

for script in os.listdir("."
):
  subprocess.call([sys.executable, script])

At this point, no amount of nested imports, side-effects or messing about with PYTHONPATH can throw your execution mechanism off guard!

The next step might be to append each result of os.listdir to your GUI.

# Using QListWidget with QListWidgetItem

for script in os.listdir("."
):
  item = QtGui.QListWidgetItem(script)
  self.mylistwigdet.addItem(item)

Then, once hitting “run”, you would do as above; loop through each item and run each script.

for i in xrange(widget.count()):
    item = widget.item(i)
    script = item.text()
    subprocess.call([sys.executable, script])


That is, unless the goal is to apply some kind of operation to a current selection context in the scene. The item names from that original example image suggest Rudi wants to apply operations to a selected rig or something. 
 

Rudi Hammad

unread,
Dec 27, 2015, 11:57:16 AM12/27/15
to Python Programming for Autodesk Maya
Thanks a lot for all your help!
Yes,the goal is to apply this to a rig.
One problem I run into at work is that, even if you have a sólid rig builder UI, some times, the carácter you are rigging has something specifiq that your rig builder can't do. So you need to add an extra script for it. This way, when you click the "rig" button, it will execute all the default scripts of the builder, plus the one you added for that specifiq feature. And I want the posibility to save that script in the UI ( in the list widget), to be able to rebuild the rig as many times I want. Does that make sence?

Marcus Ottosson

unread,
Dec 27, 2015, 12:11:14 PM12/27/15
to python_in...@googlegroups.com

Yes, the approach only works if the scripts have no relation and if they don’t need access to a currently running environment, like Maya.

If you have control of how the scripts it is meant to run are developed, a common interface should do the trick.

Here’s an example of how this works in Pyblish.

import pyblish.api

# find all scripts, and return their common interface;
# a class called "Plugin" in this case
for plugin in pyblish.api.discover():
  plugin_ = plugin()
  instantiated.process()

It takes all scripts it finds on paths registered by someone else, and expects those scripts to contain a subclass of a particular superclass provided by the framework; the Plugin class.

You could do something similar or maybe even identical to this, as this is also affecting the internal state of Maya and also deals with side-effects, using execfile as opposed to import.

Marcus Ottosson

unread,
Dec 27, 2015, 12:12:43 PM12/27/15
to python_in...@googlegroups.com

Sorry, looks like I pressed send before I finished typing up the code. Here it is again, but properly formatted.

import pyblish.api

# find all scripts, and return their common interface;
# a class called "Plugin" in this case
for Plugin in pyblish.api.discover():
  plugin = Plugin()
  plugin.process()
--
Marcus Ottosson
konstr...@gmail.com

Rudi Hammad

unread,
Dec 27, 2015, 12:25:48 PM12/27/15
to Python Programming for Autodesk Maya
Okey right now my brain hurts a little XD. I should study all that slowly. Thanks!

Benjam901

unread,
Dec 28, 2015, 7:13:27 AM12/28/15
to Python Programming for Autodesk Maya
Hey man,

I did something similar to this a short while back.

Take a look at this code, It basically does what you want but it executes scripts on directories one script at a time and it takes the file path of the script rather than using import dir.script as s etc.


Rudi Hammad

unread,
Jan 4, 2016, 8:35:09 PM1/4/16
to Python Programming for Autodesk Maya
awesome! thanks, I´ll check it out.
Reply all
Reply to author
Forward
0 new messages