View Full Version : Python + MXS
specxor 06-21-2007, 11:44 PM Hi, Guys, sorry this is bit late but its been one of those weeks. Better late than never I guess. Anyways there a a couple of ways to get python to talk to max and vice versa. The simplest way being COM. This of course requires that you have max registered as a COM server and that you have some MXS function visible to COM (if you have not used com before check the Example scripts on 3ds max disc for getting com going, very easy to do).
First off the code im posting is the most simple of examples! but it should give you a glimpse of what could be possible, which is allot.
Fist off create a really simple function in max:
fn DoSomething obj = (
try(
execute obj
return true
)catch(
return false
)
)
registerOLEInterface #(DoSomething)
As you can see there is a ultra simple function that will just execute whatever is parsed to it. Now for the Python part, this will require the win32 module.
#Import win32com.
import win32com.client
#Create a connection to Max
conn = win32com.client.Dispatch("MAX.Application.9")
#Flag as a Method otherwise python or win32com will most likely treat it as attribute.
conn._FlagAsMethod("DoSomething")
#Call 'DoSomething'
#obj.DoSomething("Box()") Thanks to Joel Hooks for pointing out the typo..
conn.DoSomething("Box()")
With any luck you should have a box sitting in the middle of you view port. As I said above this is a very simple example, I will post some more exciting ones! Its worth mentioning that python can be called from max in much the same way, although the best* work flow (at least i think so) is to create a python server, which listens for and queries max, this has some awesome work flow implications, ie lots of artists working on the same job it becomes very easy all the sudden to keep things in sink like camera animation for example... did someone say camera server?
Hope thats enough to get you guys started, as I said I will post more stuff soon!
Cheers
Dave
|
|
erilaz
06-22-2007, 12:44 AM
Thanks for setting this up Dave. Really appreciated. Can you do a copy/paste of your python resources post from the challenge thread here?
specxor
06-22-2007, 12:58 AM
I sure can:
I use python for all manor of things we have written full feature project management apps, asset browsers and a host of other bits and pieces. In terms of resources I must admit my first port of call is python.org, however I do like the oreily books "Programing Python" comes to mind. I would also recommend the Python help file that comes with the Active State (http://www.activestate.com/) distribution of python (I also think there IDE is the best, Komodo, wich is now free).
There also so some modules that I like and use all the time, I found these ones come in handy all the time:
PIL, this imaging lib is awesome I have written some really cool asset browsers that have utilised PIL, http://www.pythonware.com/products/pil/
Pyro, or Python Remote Object, I love this module for simple networking tasks, RPC and distrusted process's, http://pyro.sourceforge.net/
Twisted, is another networking module, its a bit big (theres an entire book on it), but it has some useful parts...
WxPython, this is the BEST gui lib for python, its wrapped around the C lib so its not so 'pythonic' but once your used to it or wrapped it you can build very feature rich apps very quickly and its very well documented... http://www.wxpython.org/
PyWin lib is awesome it provides access to just about everything in windows, including com/ole so working with max becomes very easy. You can do some very cool stuff with it. I don't have a link as I have no idea were i downloaded it, I know Mark Hammond wrote it (most of it??) I do believe its built into the Active State distribution that I mentioned above. (If anyone wants it just pm me)
Hope that helps, I think allot of people (maxers at least) tend to skip over python, but it is very easy to work with python in max and have python work with max (Pyro = back burner replacement)...
did someone say camera server?
What's a camera server?
Thanks for this introduction. I'm not as biased against winOS like maybe others. But OLE somehow got a 'bad bad' tag. I will have to reevaluate this.
Having a queque and a lockfile on your server that keeps track of requests could be a way to build a 'remote scene compositor' where the 'artists' could be just monkeys spread around the world.
Sidenode:
What are the legal consequences of such setups? I think most plugins aren't licensed for server setups?
Anyway:
I heard that other applications use/will use python as well - so it is propable the middleware of choice for pipelines. Though I miss the {} ...
Georg
Kermit
06-22-2007, 09:00 AM
hi,
personnaly, i use IronPython for developpe Dotnet assembly and use in 3dsmax and communicate with maxscript
less problem than OLE communication
but i don't if all "classic" python librairy can be use with ironPython
Kermit
ypuech
06-22-2007, 09:02 AM
Thanks David for the simple but very interesting example.
Yes, Python is one of the best scripting language.
I've also read an article about using 3ds Max as OLE Server (show how to communicate between XSI and Max) : http://www.sloft.net/2006/11/26/how-to-make-xsi-and-max-friends/
j-man
06-22-2007, 11:06 AM
Hi Dave,
Thanks for starting this off. Muchly appreciated! there goes my weekends!
ezza, can we have a sticky please?
Josh.
I wish that I had weekends to dedicate to this...darn.
This is a great start. I have known this was possible for a long tim but I have never look into how to do it. Time to start I guess.
Can this thread please be made sticky! It is a very important solution for Max houses that need complex pipelines. Which is exactly what I'm in the process of setting up.
I wish that I had gone with Python in the first place an not learned Perl. ah well.
erilaz
06-22-2007, 03:08 PM
Can this thread please be made sticky! It is a very important solution for Max houses that need complex pipelines. Which is exactly what I'm in the process of setting up.
What the Paul wants, the Paul gets.:D
Hi Dave,
Thanks for starting this off. Muchly appreciated! there goes my weekends!
Same here. Not that I don't have a billion other things to be learning right now, but this is too good to pass up.
What the Paul wants, the Paul gets.:D
Ok then...a three day work week, paid for six. Am I pushing it now? Thanks for making it sticky.
I just had a look at setting up OLE and that looks stright forward.
I'm looking at the example scripts, Funny...I didn't know that PEN Attribute Holder still shiped with Max:) Any way I can't find the COM scripts? What are they called? This is the Max 9 disc.
And, does 64 bit change any of this?
erilaz
06-22-2007, 03:36 PM
Any way I can't find the COM scripts? What are they called?
Sorry Paul, which COM scripts are you referring to?
ypuech
06-22-2007, 04:25 PM
Sorry Paul, which COM scripts are you referring to?
Maybe ole.ms and oledemo.xls ("Running the OLE Demo" in MAXScript Reference). Can't find them to.
cyfer
06-22-2007, 08:01 PM
oh ,.............
at last i can help Paul and Yupech :P
Samples\Scripts\Examples
There also so some modules that I like and use all the time, I found these ones come in handy all the time:
PIL, this imaging lib is awesome I have written some really cool asset browsers that have utilised PIL, http://www.pythonware.com/products/pil/
Pyro, or Python Remote Object, I love this module for simple networking tasks, RPC and distrusted process's, http://pyro.sourceforge.net/
Twisted, is another networking module, its a bit big (theres an entire book on it), but it has some useful parts...
WxPython, this is the BEST gui lib for python, its wrapped around the C lib so its not so 'pythonic' but once your used to it or wrapped it you can build very feature rich apps very quickly and its very well documented... http://www.wxpython.org/
PyWin lib is awesome it provides access to just about everything in windows, including com/ole so working with max becomes very easy. You can do some very cool stuff with it. I don't have a link as I have no idea were i downloaded it, I know Mark Hammond wrote it (most of it??) I do believe its built into the Active State distribution that I mentioned above. (If anyone wants it just pm me)
Hope that helps, I think allot of people (maxers at least) tend to skip over python, but it is very easy to work with python in max and have python work with max (Pyro = back burner replacement)...
Cheers
DaveI believe that pyWin can be found here:
http://sourceforge.net/projects/pywin32/
Great, I have it. Like I have time for this!! Damn you, damn you all to hellllllllllllllllllllllllllllll! Now I just need a quite beach, were the rest of humanity has been whipped out and the bank and tax man isn't looking for me so that I can sit down and learn some of this. The talking apes might become of bit of a distraction.
Wahooney
06-23-2007, 04:33 PM
Please pardon my eternal ignorance, but what is the advantage to this Python/MXS tie in? I haven't worked with Python before, what can it do that MXS can't?
Any example applications? In other words.
Thanks.
specxor
06-24-2007, 01:43 PM
Hi, Guys,
Fist off, Camera Server that I mentioned is a simple little app im working on, that will keep animated cameras in sync. So an animator can be animating the camera and lets say a lighter is lighting the scene then his camera will have a live link to the animators etc... If that makes sense?? I am hoping to finish it 'this' week and ill post all the source for everyone to check out hopefully there will no be to much spaghetti code in there :)
Anyways to answer a couple questions:
Wahooney, Python can't really do more then Maxscript in fact its the other way around more that python is limited to what mxs can do, were Pythons power lies is in its ability to "tie it all together" which is why its so good for building pipelines with...
PEN, I second that a quite beach were i can sit down with laptop and gets some stuff done... wait quite beach, mmm forget the laptop...
ypuech, I had actually read that link a while ago, It does however show the power of com when used to communicate through software...
Kermit, I have only played with IronPython a little bit (IronPython is a version "distro" of python that runs on the .Net virtual machine (? I think so) ) I thought the standard library was implemented? I'm not sure if Iron python makes it easier to add python scripting to a dot net app, maybe ypuech could shed some light on this?
If there any specific examples of python scripts you guys want just let me no... I am hoping to be able to show you an example of a render manger written in python (for vray standalone, but could easily add the functionality for different renders etc...) but thats a little ways off yet.
Cheers
Dave
More code coming this week!
Kermit
06-25-2007, 08:19 AM
Hi,
i've test succefully to implement a dotnet dll ( write in ironPython ) and integrate with in a maxscript rollout (thx to Yannick Puech for tutorial )
i need to try some Net 3 ( XAML ) dll for better UI ( like character vector drawing for rigging ), always with IronPython
the help tutorial mention u can import standart python library, but i do not test
i need more free time for this, it's only a idea for your post . the big advantag i see is the communication between dontnet and mxs implemente by Autodesk
Kermit
ps : maybe difficult to read me, my english is very bad, sorry
Wahooney, Python can't really do more then Maxscript in fact its the other way around more that python is limited to what mxs can do, were Pythons power lies is in its ability to "tie it all together" which is why its so good for building pipelines with...
I'd say:
Python's power is the one of a middleware.
All the c#/.net stuff is limited to winOS. Using python you can implement osindpendend clients and data parsers.
This might be based on thin ice but:
Python is definitely a stronger string and xml parser than maxscript.
I used python in the past mainly in peparing data for indesign and illustrator.
ypuech
06-25-2007, 10:11 AM
I thought the standard library was implemented? I'm not sure if Iron python makes it easier to add python scripting to a dot net app, maybe ypuech could shed some light on this?
Yes, you can extend .Net applications with ironPython.
I've only heared a little bit about ironPython. Seems powerful. It's very useful to be able to create a managed assembly and use it under 3ds Max.
RustyKnight
06-25-2007, 10:51 AM
I'm curious...with the implementation of python in maya, i'm wondering if max will head the same way??
If so, do you think it's a good thing or a bad thing?
Personally, I'd like to see a little more OO implementation in the API (I know the core API is OO, but max script isn't ... to my meger knowledge ... but this is not the place for that disscussion)
Personally. I'd like to see the scripting side updated, as powerful as it is and as simple as it can be, it can sometimes be frustrating...just gets you close enough to a solution, but not quite overline.
Just thought I'd ask the question and see what others think
ypuech
06-25-2007, 11:35 AM
Hi Shane,
I think adding Python to 3ds Max would be a pain... Maya is well designed so adding Python to it wasn't so difficult. It's not the same story for Max.
specxor
06-25-2007, 01:59 PM
I'd say:
Python's power is the one of a middleware.
All the c#/.net stuff is limited to winOS. Using python you can implement osindpendend clients and data parsers.
This might be based on thin ice but:
Python is definitely a stronger string and xml parser than maxscript.
I used python in the past mainly in peparing data for indesign and illustrator.
I agree completly, python is very good at gluing the pipeline together even more so if you have a multi package workflow so max maya fusion/shake.... and yes python string parsing is very strong along with its XML parser which is all C and well developed...
I think adding Python to 3ds Max would be a pain... Maya is well designed so adding Python to it wasn't so difficult. It's not the same story for Max.
I have to admit I would love to see python in max, although i think hell will freeze before it happens :)
Cheers
Dave
Here is one that I would like to see as it is right up the line or what I'm doing. A tie in with the Python XML parser and a data base. I gather this is possible but I haven't looked into what data bases Python will work with, I'm guessing any of them. Is this correct?
I'm guessing any of them. Is this correct?
This is correct.
The reason that hold me back from doing extensive DB stuff until now was:
Not many people like to have a DB on the same machine as a maxinstallation.
Also: not many admins like a DB that is accessible from any host.
All this leads to proxy scripts, where you have the scripts running on the DBserver that will be queried through HTTP or curl (don't know what the python name for curl is).
But speaking of xml and databases:
Maybe a XML database like eXist is a good idea, as parsing xml from/to relational db's like mysql is sometimes ugly.
Thanks, I'll dig further.
specxor
06-25-2007, 11:50 PM
MySql is really simple in Python with the 'MySQLdb' module, it makes connection and interacting with the database simple. For xml i like Element Tree which as of version 2.5 of python is in the standard lib. Its very fast and easy to use.
I do prefer to with XML than SQL, I wrote our server here in Python that works off a XML back end, its not to difficult to do, so long as you can get your head around threading etc...
Cheers
Dave
hblan
06-26-2007, 02:58 PM
cool , im waiting for it long time . with python , im free from max envirment , and free from C++ . lol .
MySql is really simple in Python with the 'MySQLdb' module, it makes connection and interacting with the database simple. For xml i like Element Tree which as of version 2.5 of python is in the standard lib. Its very fast and easy to use.
I do prefer to with XML than SQL, I wrote our server here in Python that works off a XML back end, its not to difficult to do, so long as you can get your head around threading etc...
Cheers
Dave
Just so that I'm clear on this. There is an XML data base? Is this free? Or are you writting XML files?
I'm just working on modules in Python, this is far easier then Perl that is for sure. Well for me anyway. The help files are really good so far.
Need a bit of help on packages? Is a package just a diescription file of what modules to import?
So you list the name of the package and then the names of the sub folders and then the modules in them??
There is an XML data base?
Exist:
http://exist.sourceforge.net/
Xindice:
http://xml.apache.org/xindice/
There might be others as well.
The 'drawback' of those is that you use xpath and other xml-techniques instead of godd-old-sql-syntax.
Also they are better for storing document-style-data. Relational databases seem to be better for storing data-style-data. I guess this will be a new field of research.
For now back to the XML file parsing. So in max I have the dotNetObject "system.Xml.XmlDocument" for reading and writting Xml docs. In Python I have modules that can do the same. I don't want to have to write the same code twice, once in Max script once in Python.
Can python use the same .net method as Max?
Should I write it all in Python and call the python functions from Max some how...if so...how?
I have the oposite from the above worked out in my head but that isn't the way that would be most effective if I ever want to include another app.
RealThing
06-27-2007, 04:42 AM
This is a really interesting development. I've been calling python scripts for various things from 3dsmax for a while now but to be able to do it the other way around opens up some interesting possibilities.
Thanks for posting this. Although I still hope that a native python interface finds its way into 3dsmax someday.
How are you calling the python scripts? Same way that is shown in the Project Management thread?
RealThing
06-27-2007, 02:30 PM
Since it's for in-house use only it's not nearly that refined. Currently I'm just executing python.exe <script> params (normally an xml file that's generated by the maxscript side of things) using the doscommand syntax. It pops open a dos window so not exactly transparent but it works.
Most of the python use here has avoided 3dsmax b/c of issues with integration. So it's been used for pipeline things and as runprogram calls in renderman scene files for adding and rendering of some large astronomical dataset stuff that 3dsmax just can't deal with very easily. This is integrated into 3dsmax's scene via some scripts which deal with the coordnate system translation and the exportation of the cameras into rib files and queueing the results in Deadline and such to be rendered as a layer for later compositing.
Once I have more time I'll have to look at this thread and see if there are more elegant ways to do some things. Including making some of the python scripts cull down the data sets and atleast allow some level of visualization of them within 3dsmax. I hope to move some of the logic that's currently in the 3dsmax scripts to python now that it appears there are some easier ways to get data back and forth. Allowing me to reuse alot of code in other 3d apps.
This is exactly what I'm looking at as well. I don't want to have CMD popping up every time something is run.
Once I get things working I will post examples here. Could be a while as I just found out that the client now needs something really fast so I'm going to hobble together a solution that should get them further then what they currently have which is nothing.
specxor
06-28-2007, 06:36 AM
Hi, Guys,
I prefer to use COM instead of doscommand etc... Its very easy to make class written in python into a COM service. Here is a repost of the code in the Project Management Thread.
#A simple Python COM server, as simple as it gets.
class PythonComClass:
_public_methods_ = [ 'SplitString','SomethingElse' ]
_reg_progid_ = "PythonDemos.Utilities"
#Make sure you generate a new Class ID, use pythoncom.CreateGuid()
_reg_clsid_ = "{41E24E95-D45A-11D2-852C-204C4F4F5020}"
def SplitString(self, val, item=None):
"""Splits a string"""
import string
if item != None: item = str(item)
return string.split(str(val), item)
def SomethingElse(self):
"""Some other method"""
return "Something Else"
def __PrivateMethod(self):
return "This is a private method"
#Make sure this module has not been imported. Register COM server
if __name__=='__main__':
print "Registering COM server..."
import win32com.server.register
win32com.server.register.UseCommandLine(PythonComClass)
############################################
#MXS
releaseAllOLEObjects()
obj = createOLEObject("PythonDemos.Utilities")
obj.SplitString("asd_asd", "_")
I would normally have a bunch of private methods that handle connecting to servers etc (or whatever you want them to do). Then just have a few public methods to call, this is a really powerful way to talk to python as you can of course return data as well....
Cheers
Dave
RealThing
06-28-2007, 03:36 PM
Thanks for that Dave. Very interesting indeed.
I could be wrong here so please correct me if I am. But the one downside I see is that the python code itself is influenced by the target host application....which is less than ideal when you're trying to use python as a neutral middle ground for a pipeline that consists of multiple applications. So if you want to use your python code from multiple applications extra care would have to be taken to wrap the python application/scripts in COM in a way that the application/script can also be run outside of the COM interface for programs that natively support python. This would especially be true in mixed OS environments where you can't count on COM support being available.
I guess that's what we live with until 3dsmax has a native python interface...which one can only hope is soon.
specxor
06-28-2007, 11:35 PM
Thanks for that Dave. Very interesting indeed.
I could be wrong here so please correct me if I am. But the one downside I see is that the python code itself is influenced by the target host application....which is less than ideal when you're trying to use python as a neutral middle ground for a pipeline that consists of multiple applications. So if you want to use your python code from multiple applications extra care would have to be taken to wrap the python application/scripts in COM in a way that the application/script can also be run outside of the COM interface for programs that natively support python. This would especially be true in mixed OS environments where you can't count on COM support being available.
I guess that's what we live with until 3dsmax has a native python interface...which one can only hope is soon.
I agree 100% until max has python implemented as a scripting language (I'm not holding my breath) we are stuck with either wrapping existing apps that we have written so there COM compatible or parsing commands via command line etc... On the mixed os side of things, I generally will write an app once and then do some platform testing to determine whether or not to register classes with com etc...
Cheers
Dave
d3coy
07-02-2007, 12:34 AM
A safe way to construct a "Python middleground" would be to open a socket to a server (Python scripted) that holds all of your global methods (database access, whether sql or xml or whatever, project management functions, etc) and could be called from anywhere with access. You'd only ever have to write an interface to the server whenever you add other packages to the pipeline.
It'd require extra initial setup, setting up a TCP server, writing the byte-headers of your different return values for the functions, etc, but it'd pay off. If many computers will be using the functions at once, the server could be multithreaded with stackless python or the standard thread api. OS independence, package independence. Just a thought; I just don't like depending on a Windows-only interop service.
If only something like Pyro could be used from within Max.
specxor
07-02-2007, 11:26 AM
A safe way to construct a "Python middleground" would be to open a socket to a server (Python scripted) that holds all of your global methods (database access, whether sql or xml or whatever, project management functions, etc) and could be called from anywhere with access. You'd only ever have to write an interface to the server whenever you add other packages to the pipeline.
It'd require extra initial setup, setting up a TCP server, writing the byte-headers of your different return values for the functions, etc, but it'd pay off. If many computers will be using the functions at once, the server could be multithreaded with stackless python or the standard thread api. OS independence, package independence. Just a thought; I just don't like depending on a Windows-only interop service.
If only something like Pyro could be used from within Max.
Hi, d3coy,
Thats almost the exact workflow I use on a day to day basis. Its easy (relatively easy). I talk to python servers through a COM class I have written that creates the Pyro connection which max communicates through... I will try and put together and example this week for everyone...
The other approach which i prefer and have used with success is to create your own slave app that runs on each machine, I'm currently porting my pyro version to twisted to take advantage of asynchronous networking which is great if you want to write a render manger or "allot" of other things... again ill try and post some examples as time permits...
Cheers
Dave
d3coy
07-02-2007, 03:30 PM
Awesome spec,
I was thinking about it some more, and thought it might not make sense to completely build my own system when something like Pyro exists. I'd love to see how you're accessing Pyro objects through COM. Otherwise It'd involve a lot of python socket programming with a .net socket app that MXS uses to bridge to the python server. Can Maya's and XSI's python integration import modules like Pyro?
*edit: I need to look more at Twisted. Its hard to find tutorials on the web for it though, I suppose because there are so many books on the subject.
specxor
07-03-2007, 12:26 AM
Awesome spec,
I was thinking about it some more, and thought it might not make sense to completely build my own system when something like Pyro exists. I'd love to see how you're accessing Pyro objects through COM. Otherwise It'd involve a lot of python socket programming with a .net socket app that MXS uses to bridge to the python server. Can Maya's and XSI's python integration import modules like Pyro?
*edit: I need to look more at Twisted. Its hard to find tutorials on the web for it though, I suppose because there are so many books on the subject.
Ill try and post the code up for you asap... I would also love to no whether maya or XSI can import modules as well, I'm making the assumption and saying yes, but still not sure...
Certainly coding an app thats working with sockets is hard work, rather more time consuming, and thats before we get into threading, thread locking etc... Allthough .Net and python communication is certainly something I will do some reasearch into...
Cheers
Dave
erilaz
07-03-2007, 01:11 AM
Loving the momentum of this thread guys!
Hopefully i'll actually get a chance to try some of this out when my work has calmed down!
I'm loving this thread as well.
A couple of questions. Can one of you please tell me what Pyro and Twisted are and what they do? I'm looking them up but I'm going to quess that I'm not going to figure out how you are using them with Max from what I will read on the web.
Thanks guys. This thread is going well.
RealThing
07-03-2007, 02:40 PM
Pyro is a Python Remote Object library written in python itself. Basically it allows python code segments to sit on a centralized server and clients can execute the code from anywhere on the network. You can think of it as distributed COM for python. More info and documentation can be found here http://pyro.sourceforge.net/
Twisted is a Python event driven network engine also written in python. I'm not that familiar with it only know that it's used as a python based web framework although I prever Django. Maybe someone else can elaborate on how this fits into their pipeline and maxscript. The projects home page is http://twistedmatrix.com/trac/.
Ok, how does Pyro differ them setting a path to a folder on the server were you have modules that can be used? I might be missing something major here.
d3coy
07-03-2007, 03:30 PM
You could definitely have modules on the network that you access from each station, but the code is still basically executed on the station that called it. Pyro lets you call methods and props on an object just as if it were local, but the processes happen on the server remotely.
You could definitely have modules on the network that you access from each station, but the code is still basically executed on the station that called it. Pyro lets you call methods and props on an object just as if it were local, but the processes happen on the server remotely.
Sorry for my ignorance, what is the advantage of this?
d3coy
07-03-2007, 04:41 PM
I think for a lot of tasks it wouldn't matter. If you have multiple users making queries to a sql db then the db server is going to handle the multiple requests at once for you anyways. But if you have some methods that make file system traversals or even more potentially volatile, executing MXS on scene files, you might want to have a remote object handle these things so these processes don't potentially overlap from multiple users, causing who knows what kind of havoc... But if you're the only one that'll be executing this kind of code, there isn't a need for a server like that.
I think that I'm starting to get this. I will be looking into this more as this project moves forward into the next phases so I'm sure that I will have more questions then.
Thanks for your time.
specxor
07-04-2007, 12:54 AM
Pyro is a Python Remote Object library written in python itself. Basically it allows python code segments to sit on a centralized server and clients can execute the code from anywhere on the network. You can think of it as distributed COM for python. More info and documentation can be found here http://pyro.sourceforge.net/
Twisted is a Python event driven network engine also written in python. I'm not that familiar with it only know that it's used as a python based web framework although I prever Django. Maybe someone else can elaborate on how this fits into their pipeline and maxscript. The projects home page is http://twistedmatrix.com/trac/.
For me the only reason to use twisted (realtive to our 3d work) is for its asynchronous networking, its dead easy to write tcp servers. Also the Perspective Broker module is a really easy way to create authenticated RPC servers. Although for simple networking tasks the ease of pyro is second to none.
Anyways here are some example of using Pyro, just remeber these are quick hacks at best, if you were to implement something like these there would be allot of error handling etc one would want to do!
now for the code, here is a simple pyro server, I have pulled this code out some other apps so there is some stuff that does not need to be there etc... for example this server does not need to be run on a therad etc...
"""
Really Simple Example of Pyro Server...
I have pulled lots of code out of this, hope its not to spaghetti like!
"""
import Pyro.core
import Pyro.naming
import threading
from Pyro.errors import PyroError, NamingError
ServPort = 9001
"""
Pyro Proxy, subclassed from Pyro.core.ObjBase, this class will be callable,
from connected clients.
"""
class CameraServer(Pyro.core.ObjBase):
"""Pyro Proxy"""
def __init__(self):
Pyro.core.ObjBase.__init__(self)
def HelloWorld(self, name):
if type(name) == str:
print "Hello, %s" %(name)
return True
else:
return False
"""
Run server on a thread (pyro is multi threaded,
I normaly start pyro on a new thead when im using it with a gui.
"""
class CreateServer(threading.Thread):
"""Server Thread"""
def __init__ (self, **kwds):
self.daemon=Pyro.core.Daemon(port = ServPort)
threading.Thread.__init__ (self, **kwds)
self.setDaemon(0)
self.start()
def run (self):
"""Start Pyro Server"""
Pyro.core.initServer()
uri=self.daemon.connect(CameraServer(),"CameraMan")
self.daemon.requestLoop()
if __name__=="__main__":
#Start the Server
a = CreateServer()
Now here is a client that will call the method on the server,
import Pyro.core
import Pyro.naming
from Pyro.errors import PyroError, NamingError
##Connect To Pyro Server, needs the IP, Port and the Remote Method Name as a string. Will return a Pyro Proxy
def ConnectToPyro(ServIp, ServPort, ServMethod):
PugNet = Pyro.core.getProxyForURI("PYROLOC://%s:%s/%s" % (ServIp, ServPort, ServMethod ))
PugNet._setNewConnectionValidator
return PugNet
if __name__ == "__main__":
con = ConnectToPyro("127.0.0.1", 9001, "CameraMan")
print con.HelloWorld("CgTalkers")
I hope that show just how powerful this can be when used in the right circumstances... Here is an example using the COM class i posted earlyer, I have not had time test this code... Its worth mentioning this class is real hack ill post up one thats written "properly" in the next couple of days.
##Connect To Pyro Server, needs the IP, Port and the Remote Method Name as a string. Will return a Pyro Proxy
def ConnectToPyro(ServIp, ServPort, ServMethod):
PugNet = Pyro.core.getProxyForURI("PYROLOC://%s:%s/%s" % (ServIp, ServPort, ServMethod ))
PugNet._setNewConnectionValidator
return PugNet
#A simple Python COM server, as simple as it gets.
class PythonComClass:
_public_methods_ = ['SplitString', 'ConnectToPyro', 'QueryPyroMehtod']
_reg_progid_ = "PythonDemos.Utilities"
#Make sure you generate a new Class ID, use pythoncom.CreateGuid()
_reg_clsid_ = "{41E24E95-D45A-11D2-852C-204C4F4F5020}"
def SplitString(self, val, item=None):
"""Splits a string"""
import string
if item != None: item = str(item)
return string.split(str(val), item)
def ConnectToPyro(self, serv, port, meth):
try:
self.PyroConn = ConnectToPyro(serv, port, meth)
except:
print "Error connecting to Pyro"
def QueryPyroMehtod(self):
"""Talk to Pyro"""
return self.PyroConn.SomeRemotMethod("Some Data")
def __PrivateMethod(self):
return "This is a private method"
#Make sure this module has not been imported. Register COM server
if __name__=='__main__':
print "Registering COM server..."
import win32com.server.register
win32com.server.register.UseCommandLine(PythonComC lass)
Hope thats useful...
Cheers
Dave
d3coy
07-05-2007, 03:49 PM
Thanks a ton spec, I'll give the com class a go and report back how I faired (I know you said it was quick code, I'll give it a shot anyways :) )
specxor
07-05-2007, 11:47 PM
Thanks a ton spec, I'll give the com class a go and report back how I faired (I know you said it was quick code, I'll give it a shot anyways :) )
If you have any trouble post the tracebacks and ill get on it, "Hopefully" ill get time this weekend to write these up properly for everyone... Using the COM class can be hit and miss it can require a restart of the machine after having had made changes etc... I typically call the class and debug it before registering it as COM service.
Cheers
Dave
TheIvIaxx
07-08-2007, 08:55 PM
Thanks for this post, seems to be promising. However I also see that MXS has .NET capabilities now so i'm kind of curious if there are serious limitations to python or .net. I understand this sounds like a x vs. y question :( Try to be objective. Can the two languages be used in relatively the same way?
RealThing
07-09-2007, 04:56 AM
i'm kind of curious if there are serious limitations to python or .net. I understand this sounds like a x vs. y question :( Try to be objective. Can the two languages be used in relatively the same way?
For the most part I would say yes and that it depends.
If you're only concern is 3dsmax running on Windows then maxscript and .NET should offer you alot of possibilities.
You can't actually compare Python to .NET as one is a scripting language and the other is a framework. In over all power Python has alot of libraries which allow you to do anything that you can do within the .NET framework and then some. If you choose to use IronPython you also have full access to the .NET framework from within Python as well but it's not as portable (windows only).
So currently the only advantage .NET has is that the bridge between it and maxscript is already available in 3dsmax. But since Python is now built into a growing number of 3d and compositing apps and alot of studio's have pipelines built on or around Python connecting 3dsmax to Python is attractive. It also provides a portable middle ground for common code. So that a maxscript in 3dsmax running on windows can call the same python functions as a similar script in maya or nuke running on windows or linux.
Python has been around for 16 years and has been used in pipelines for most of those. So I would say that Python is production proven. http://www.python.org/about/success/ilm/
On the other hand my experience with the .NET framework on windows has been that the framework is pretty fragile. We use Deadline at work which relys on the .NET framework and we have had to go through the pleasure of removing and reinstalling the .NET framework on a couple of workstations to get things to work correctly after they suddenly stop working for no reason. Luckily the process is documented in MS's knowledge base but it involves manually removing a bunch of files, directories, and registry keys. Followed by reinstalling the framework.
Hopefully that avoided the whole x vs y thing as much as possible.
ehulser
09-06-2007, 11:02 PM
This is a really useful thread guys, thanks. We're running into a lot of the same issues at Blur, we use python for almost all our external tools & tools within XSI (since it supports it) but for all our MAX stuff we're still using MS. For us, it seemed the things that were most useful from Python to tie everything into our pipeline is object-oriented classes, easy XML read/write, and regular expressions - all things which maxscript lacked.
We've actually come up with some useful stuff for improving the power of scripting that mimics the python structure, while keeping it all inside 3dsMax Script so you don't have to work through COM. The one that I've found most helpful in creating more advanced apps inside maxscript is the OOP model, it allows you to create classes within maxscript that can be inherited from, and passes in itself as its first variable to a function, essentially be wrapping the struct Value inside of a classDef (another value that exposes all the same features of a class in python): eg:
local classA = classDef #ClassA (
struct _ClassAStruct (
data = undefined,
name = "",
function __init__ self name data:undefined = (
self.name = name
self.data = data
)
)
)
local classB = classDef #ClassB (
struct _ClassBStruct (
function __init__ self = (
ClassA.__init__ self "MyName" data:10
)
)
) baseClass:( classA )
local b = classB()
print b.name ---> "MyName"
print b.data ---> 10
--------------------------
its really been invaluable to me in making more complicated maxscript tools. it works almost exactly like python, and while it doesnt port directly externally, it is similar enough that if we need the same functionality internally of max & externally from max it can be re-written almost 1-1.
The other is the regular expression engine, and that was simply a matter of wrapping the .Net RegularExpression library in a DLL.
We're really trying hard to get the Blur Beta site back up, its our intention to release these DLL's publically. I'll let you know as soon as we do, but if anyone has any suggestions based on that example, or has any questions, lemme know. I hope that helps a bit!
ehulser
09-06-2007, 11:06 PM
also, if anyone is interested in the DLLs for this, I can talk to my supervisor and see about putting just those up until the beta site is up. They've been extremely helpful for me in programming and I think could be really helpful for everyone else as well.
maxplugins
09-07-2007, 09:06 AM
Hi Eric,
if you need somewhere to put them until the BlurBeta site is back, let me know.
Dave
specxor
09-10-2007, 05:37 AM
Hi Eric,
I love where you guys are headed with this, currently I'm using A LOT of COM to get max talking to the rest of our pipeline, consequently anything that gets me away from COM I am very interested in!
The OOP example you showed below is very exciting, I can think of a dozen scripts and tools that i have written that would immedieatly benifit from this... Nice work, and I can not wait to try the dll's when blurbeta is back up.
Cheers
Dave
erilaz
09-10-2007, 06:10 AM
also, if anyone is interested in the DLLs for this, I can talk to my supervisor and see about putting just those up until the beta site is up. They've been extremely helpful for me in programming and I think could be really helpful for everyone else as well.
I think I can safely say that everyone will be interested. :)
Great to see the thread still evolving! We need to start wikifying some of this.
d3coy
09-10-2007, 04:38 PM
Excellent, eagerly awaiting those dll's ehulser :)
ypuech
09-10-2007, 05:08 PM
This seems very powerful Eric. Can't wait to use these DLL's.
Same here, just about to start writting the python portion of the tool that I have been working on.
ehulser
09-10-2007, 06:59 PM
Cool, thanks for the support for the use of these DLL's, I can take this to my supervisor and use it to really push for the beta site to be up. I just have to work on some documentation stuff for everyone to use as well. I'll keep everyone posted, hopefully we'll get it out there for everyone soon.
Kramsurfer
09-13-2007, 05:25 PM
I'm on the wait list too... Where would the 3dsmax world be without Blur's generous contributiion to the 3ds World ? ? ?
Thanks
TheIvIaxx
09-13-2007, 07:09 PM
I am still trying to get the COM stuff working 100%. It's hit or miss just on telling max to open a file. Sometimes max will just outright crash, sometime is get:
** system exception **
during OLE automation function call
Othertimes i get pywintypes.com_error: CONNECT_E_NOCONNECTION. I'm not sure if I am missing something or what:
...
m = win32com.client.Dispatch("MAX.Application.8")
m._FlagAsMethod("loadMaxFile")
...
try:
m.loadMaxFile(self.f)
except pywintypes.com_error, e:
print e[1]
specxor
09-14-2007, 12:33 AM
Hi Brett,
I just did a quick test and had no problems,
>>> obj = win32com.client.Dispatch("MAX.Application.9")
>>> obj._FlagAsMethod("loadmaxfile")
>>> obj.loadmaxfile("C:\\TestMax_1.max")
I would suggest double checking that "loadmaxfile" was registered as a OLE interface in max,
registerOLEInterface #(loadmaxfile)
In general though I have not had many problems with python to max, I do occasionally get errors going the other way (max to python). Although I have not used COM with max 8 in a while.
Let me know how you go...
Cheers
Dave
Joel Hooks
09-17-2007, 08:40 PM
#Import win32com.
import win32com.client
#Create a connection to Max
conn = win32com.client.Dispatch("MAX.Application.9")
#Flag as a Method otherwise python or win32com will most likely treat it as attribute.
conn._FlagAsMethod("DoSomething")
#Call 'DoSomething'
obj.DoSomething("Box()")
The obj.DoSomething("Box()") threw me. I had to use conn.DoSomething(("Box"))... Maybe this is obvious, but I thought others might have had similar problems.
RustyKnight
09-17-2007, 09:51 PM
Maybe this is obvious, but I thought others might have had similar problems.
Don't be afraid to post the bluntly obvious, it's sometimes what throws us.
specxor
09-18-2007, 12:15 AM
I agree with RustyKnight, who knows how many times a simple mistake has caused me greif!
The obj.DoSomething("Box()") threw me. I had to use conn.DoSomething(("Box"))... Maybe this is obvious, but I thought others might have had similar problems.
Nice catch I cant believe I did not see that before I posted it up! I hope that did not cause anyone problems....
Cheers
Dave
martinB
09-19-2007, 06:18 PM
Just a quick post to say Hi and Thanks very much! This has been very interesting to read along, even though I have very little experience with COM, .Net or Python.
One question though: How do you pass variables/data back an fourth when interfacing with Python via COM? Can I 'send' an array or a struct to Python?
Cheers
-- MartinB
Joel Hooks
09-19-2007, 10:08 PM
Just a quick post to say Hi and Thanks very much! This has been very interesting to read along, even though I have very little experience with COM, .Net or Python.
One question though: How do you pass variables/data back an fourth when interfacing with Python via COM? Can I 'send' an array or a struct to Python?
Cheers
-- MartinB
With the OLE you can only send simple type, INT, String, ect. I don't know if the same is true for COM. Be cooler if you could trade typed objects!
specxor
09-20-2007, 04:59 AM
Just a quick post to say Hi and Thanks very much! This has been very interesting to read along, even though I have very little experience with COM, .Net or Python.
One question though: How do you pass variables/data back an fourth when interfacing with Python via COM? Can I 'send' an array or a struct to Python?
Cheers
-- MartinB
Hi, Martin,
Just to elaborate on Joel's post, OLE objects in Max can receive(and send) arrays, ints, floats, bools, colours, strings and undefined. These are handled with the SafeArrayWrapper. Unfortunately more complex types such as structs or max objects cannot be parsed through COM. COM implements the VARIANT data structure, for instance when you send an int from python via COM it is converted to VARIANT type VT_14 and on the other end Max is able to convert this back into an int.
Just look up SafeArrayWrapper in the max help, there is a pretty good explanation of it, alternatively just search through the MSDN stuff and it will pop up.
Cheers
Dave
martinB
09-20-2007, 06:55 PM
Dave & Joel, thanks for the info!
-- MartinB
erilaz
09-26-2007, 02:08 PM
It probably sounds sad, but I just got the first post example running and I felt a little thrill of excitement.
I'm going to buy you a round whenever I see you David. :beer:
cyfer
09-26-2007, 06:14 PM
this work
import win32com.client
conn = win32com.client.Dispatch("MAX.Application.9")
conn._FlagAsMethod("DoSomething")
for i in range(1,11):
conn.DoSomething("Box position:[10,10,10] length:10 Width:10 height:10")
#print i
but
import win32com.client
conn = win32com.client.Dispatch("MAX.Application.9")
conn._FlagAsMethod("DoSomething")
for i in range(1,11):
conn.DoSomething("Box position:[i*10,i*10,i*10] length:10 Width:10 height:10")
#print i
doesn't ??
RustyKnight
09-26-2007, 10:19 PM
conn.DoSomething("Box position:[i*10,i*10,i*10] length:10 Width:10 height:10")
The problem has to do with how "i" is been converted. From what I can tell, I would say it is a direct conversion to string value (ie "i*10", not (the value of (i = 2) * 10) = 20)
I'm not a phython developer, but I think
conn.DoSomething("Box position:[" + i*10 + "," + i*10 + "," + i*10 + "] length:10 Width:10 height:10")
Should give you the result you after...or something simular to it.
Shane
RustyKnight
09-26-2007, 10:20 PM
It probably sounds sad, but I just got the first post example running and I felt a little thrill of excitement.
I'm going to buy you a round whenever I see you David. :beer:
It's not sad at all! And if I know the other developers on this forum, they are probably feeling excited with you!! And yes, Dav, we all owe a round!!
Shane
cyfer
09-26-2007, 11:03 PM
@ RustyKnight
conn.DoSomething("Box position:[" + i*10 + "," + i*10 + "," + i*10 + "] length:10 Width:10 height:10")
AFAIK .. you should use single quotes inside double quotes to avoid conflicts in Python
So , it should go
conn.DoSomething("Box position:[' + i*10 +',' + i*10 + ',' + i*10 + '] length:10 Width:10 height:10")
however , this either doesn't work , the problem i see is i'm not sure what's going on here
i mean starting from
Conn.DoSomething(-- aren't we maxscripting here and not pythonning ?)
and we're not bothered how python handles conversion to strings ??
RustyKnight
09-27-2007, 12:41 AM
Conn.DoSomething(-- aren't we maxscripting here and not pythonning ?)
and we're not bothered how python handles conversion to strings ??
That's exactly right and that's exactly your problem.
Basically what you were saying to maxscript was "i*10" which means nothing to maxscript, "i" is undefined as far as maxscript is concerened (or worse, equal to something you don't know)!!
You need to evaluate the string so maxscript reads it as;
...assumining i = 10
"Box position:[' + i*10 +',' + i*10 + ',' + i*10 + '] length:10 Width:10 height:10"
="Box position:[' + 10*10 +',' + 10*10 + ',' + 10*10 + '] length:10 Width:10 height:10"
="Box position:[100,100,100] length:10 Width:10 height:10"
And pass THIS value to maxscript, where it can then evaluate the value.
Previous, as I said eairler, maxscript had no concept of what "i" is or it's value, it is out side of it's context, "i" is only valid within python, or if you like, with in the local context of the loop...it is not translated over to max...(this is not totally accurate, but the concept is the same)
Again, I'm not a python developer and I've not tried any of this, I just like the idea!
Try this, in maxscript:
execute "Box position:[i*10,i*10,i*10] length:10 Width:10 height:10"
and see what happens, because that is, in effect, what you are saying.
I hope this makes some kind of scense, not having python in front of me, nor never having done this kinda work, I can only "assume" that this is correct, but as far as I can tell, "i" is not been evaluated as a variable, but a litrial.
Shane
cyfer
09-27-2007, 01:46 AM
well , eh this is more confusing !
cause .. in the first post in this thread , we didn't define anything but an empty function
and in python we excuted this function and provided the function definition !
i do see that maxscript can't understand what is (i) , but as i said .. this is more confusing
python is passing what to maxscript ? only strings ?
all the benefit of communication is passing the green words as mxs commands ?
cause clearly this is what you tell when you say
Try this, in maxscript:
Code:
execute "Box position:[i*10,i*10,i*10] length:10 Width:10 height:10"
and see what happens, because that is, in effect, what you are saying.
RustyKnight
09-27-2007, 02:06 AM
Hay cyfer!
Hay, I could be completely wrong here, as I said, I have no experience in this particular area, but from you original post, that's what jumped out at me
conn.DoSomething("Box position:[10,10,10] length:10 Width:10 height:10")
conn.DoSomething("Box position:[i*10,i*10,i*10] length:10 Width:10 height:10")
The second statment says to me, pass the string value "Box position:[i*10,i*10,i*10] length:10 Width:10 height:10" to max and max is going "I don't know what i is and undefined * 10 is not a valid calculation!?"
I just had a look at this line
"Box position:[' + i*10 +',' + i*10 + ',' + i*10 + '] length:10 Width:10 height:10"
and I'd be interested to know, is the " i * 10 " been evaluated to a final value (ie i = 10; i * 10 = 100) or been passed through as a string literal "i*10"
Basically, what you want to do is evaludate the result of " i*10 " before it gets to max and pass that result through, not the calculation...
Have you tried assigning the final result to a string value first and passing that in???
result = i * 10
evaluateThis = "Box position:[" + result + "," + result + "," + result"] length:10 Width:10 height:10"
conn.DoSomething(evaluateThis)
And yes, I want to concat the "evaluteThis" string
So that max will recieve the string:
Box position:[100,100,100] length:10 Width:10 height:10
Assuming that i is 10
Joel Hooks
09-27-2007, 02:12 AM
"python is passing what to maxscript ? only strings ? "
This is essentially the case.
RustyKnight
09-27-2007, 02:28 AM
"python is passing what to maxscript ? only strings ? "
This is essentially the case.
A nice and simple response...I like it
cyfer
09-27-2007, 02:37 AM
joel & rustyknight
thanks guys , now there is no confusion ... but frustration !
RustyKnight
09-27-2007, 02:51 AM
thanks guys , now there is no confusion ... but frustration !
Try compiling a C++ solution then talk to me about frustration!! ;) Glad we could be of help!!
cyfer
09-27-2007, 02:55 AM
Try compiling a C++ solution then talk to me about frustration!! ;) Glad we could be of help!!
failed to learn it 8 years ago ! lol
specxor
09-28-2007, 05:57 AM
It's not sad at all! And if I know the other developers on this forum, they are probably feeling excited with you!! And yes, Dav, we all owe a round!!
Shane
Hi Guys,
First off Martin, Shane your more than welcome, I'm just glad that I can give something back to the community. One of these day we will have to get together and paint the town red...
As Shane and Joel correctly pointed out, in this case just strings are being parsed, that is not to say that other data type cannot be parsed across. When it come to formating strings for things like this I would typically format it this way:
for i in range(1,11):
conn.DoSomething("Box position:[%s*10,%s*10,%s*10] length:10 Width:10 height:10" % (i,i,i))
In this case the "%" character which marks the start of the 'specifier'. "s" will convert any python objects into a string, the same as going str(i). At the end of the string we give it a tuple of out variables, in this case we want i there each time so its just (i,i,i) these variable could had have been any python obj!
Cheers
Dave
cyfer
09-28-2007, 07:08 AM
for i in range(1,11):
conn.DoSomething("Box position:[%s*10,%s*10,%s*10] length:10 Width:10 height:10" % (i,i,i))
In this case the "%" character which marks the start of the 'specifier'. "s" will convert any python objects into a string, the same as going str(i). At the end of the string we give it a tuple of out variables, in this case we want i there each time so its just (i,i,i) these variable could had have been any python obj!
Cheers
Dave
thanks dave for the help
i'll reRead this thread from the beginning ...
Chris
10-02-2007, 10:05 PM
So using Com, would there be a way to pass a bitmap object to max somehow? or would the best method be to open a PIL image, convert it to an array, pass that to max & use set pixels or something to recreate an bitmap? I'm guessing that would be fairly slow...
specxor
10-03-2007, 12:48 AM
Hi Chris,
That would work just fine but as you rightly pointed out it would be pretty slow, other alternatives would be to just parse the path to the image to max and open it that way. I guess it depends on what you doing, you could also use PIL to save a temp image and then parse the temp file path to max...
Cheers
Dave
specxor
10-03-2007, 04:00 AM
Hi Guys,
This is a little script I quickly through together for a mate and thought some of you might like it. You can parse commands from max to python and have the tracbacks and stdout returned to you.
Here is a simple example:
http://forums.cgsociety.org/attachment.php?attachmentid=118728&stc=1
Here is an example of a traceback:
http://forums.cgsociety.org/attachment.php?attachmentid=118729&stc=1
Anyways time for some code:
here is the python code:
"""
Simple Com Class for parsing commands to the python.
Will return sys.stout or in the event of a exception, it will catch the error
and return the traceback.
Crafted By
David Mackenzie
Notes:
- If you get a error in max that is something like "Cannot create instance of (com class)
try registering the Com Class from a admin account.
- This is just a hack, so if for some reason your computer self destructs its not my fault.
"""
import sys
import os
import win32com.server.register
Writing = True
def TBWrite():
"""Returns the traceback as a string, VERY handy dandy biatch"""
import traceback
return traceback.format_exc()
#Catch sys.stdout, this is what would normaly be returned to the screen by python
class CatchOut:
def __init__(self, obj):
"""obj requires the method COut"""
self.Obj = obj
def write(self, data):
"""This method catches sys.stdout, stdout expects a write method"""
self.Obj.COut(data)
#global Writing
#Writing = False
class MXSPrompt:
_public_methods_ = [ 'RunCom' ]
_reg_progid_ = "DaveTools.MXSPrompt"
_reg_clsid_ = '{CF24CDE3-680B-4A38-82E0-958C57921AF7}'
def __init__(self):
self.Buffer = ""
self.StdOut = CatchOut(self)
#sys.stderr = self.StdOut
sys.stdout = self.StdOut
def RunCom(self, commstr):
"""Method that is visible to COM"""
try:
global Writing
self.Buffer = ""
exec commstr
"""
while(Writing):
pass
Writing = True
"""
return self.Buffer
except:
return TBWrite()
def COut(self, dstr):
"""Just Updates the Buffer"""
self.Buffer = self.Buffer + dstr
if __name__ == "__main__":
win32com.server.register.UseCommandLine(MXSPrompt)
And now for the max code:
/*
Just a quick hack to demonstraight some python in max. This is a very script on both ends.
If there is any interest I will develop it further.
crafted by, David Mackenize
Notes:
-Any strange errors, python or max please send to me.
-I would recomend, where ever you would like to place a tab insert 4 'spaces'
-You might find that if you have 2 or more Dialogs open (of this script) the previous ones
will drop/loose there connection with COM.
Cheers
Dave
*/
fn GetComObj = (
try(
o = createOLEObject "DaveTools.MXSPrompt"
return o
)catch(
print "error create ole object"
return False
)
)
rollout pyprompt "Python Prompter" (
group "Py Prompt" (
edittext py_out "" height:125
edittext py_in "" height:150
)
button btn_submit "Submit" align:#right
local obj = GetComObj()
on btn_submit pressed do(
t = obj.RunCom py_in.text
py_out.text = t
)
)
createDialog pyprompt 450 350
Cheers
Dave
specxor
10-19-2007, 07:00 AM
Hi Guys,
A couple people following the thread have asked about some database code, I did have some stuff I wrote ages ago, which for whatever reason has seemingly disappeared from my hard drive! None the less I had been promising to post some code for a long time, I finally got off my ass and wrote some new stuff...
So here a really simple class to demo straight saving maxfiles to (or any data for that matter) to a database (I was using MySQL i have tested the code with anything else).
I will post a com version later tonight.... anyways enough jibba jabba here is the code, if you get any errors just post them or pm me and yes I was lazy and did not comment my code I will fix this later though...
Cheers
Dave
"""
Demo Class showing interaction with MySQLdb.
The Class assumes there is db called 'mymaxfiles' and that it has a table called 'maxfiles'. Its just a basic example of how one
my want to store some files etc...
All the methods below assume the database mymaxfile exists as well.
Crafted By,
David Mackenzie
First off I don't pretend to be some SQL hacker! I just know what I need to....
This is a simple class for interacting with simple db and table. It could easily be modified to do allot more.
You will also require MySQLdb for this to work you can download here "http://sourceforge.net/projects/mysql-python".
I should also point out that I have not debugged this a great deal, I have however had no errors thrown in all my testing,
if you do get an error just shoot it acrros to me...
Cheers
Dave
"""
import MySQLdb as mys
import os
import os.path as pt
def InsertMaxFile(thefile):
db = mys.connect(host="localhost", user="root", passwd="daveRoot", db="mymaxfiles")
mycurs = db.cursor()
mycurs.execute("INSERT INTO maxfiles (files) values('%s')" % (thefile))
db.commit()
return True
def CreateTable(self):
try:
db = mys.connect(host="localhost", user="root", passwd="daveRoot", db="mymaxfiles")
mycurs = db.cursor()
db.commit("CREATE TABLE maxfiles (id INT NOT NULL AUTO_INCREMENT, files varchar(256) NOT NULL, primary key(id));")
return True
except:
return [False, TBWrite()]
def TBWrite():
import traceback
return traceback.format_exc()
class MaxFileSaver:
def __init__(self, server, username, password, database):
try:
self.db = mys.connect(host=server, user=username, passwd=password, db=database)
self.Cursor = self.db.cursor()
self.Connected = True
self.Commited = True
except:
self.Connected = False
self.db = None
self.Cursor = None
self.Commited = True
print TBWrite()
def InsertFile(self, thefile):
if self.Connected == True:
try:
self.Cursor.execute("INSERT INTO maxfiles (files) values('%s')" % (thefile))
self.Commited = False
return True
except:
return [False, TBWrite()]
else:
return [False, "Something went wrong"]
def CommitChanges(self, yayorney):
if self.Connected:
if yayorney == True:
try:
self.db.commit()
self.Commited = True
return True
except:
self.Commited = False
return [False, TBWrite()]
else:
return [False, "Not Connected"]
def GetFiles(self):
if self.Connected:
try:
self.Cursor.execute("SELECT * FROM maxfiles")
return (self.Cursor.fetchall())
except:
return [False, TBWrite()]
def SetFile(self, theid, thevalue):
if self.Connected:
try:
print self.Cursor.execute("UPDATE maxfiles\nSET files='%s' WHERE id='%s'" % (thevalue, theid))
return True
except:
return [False, TBWrite()]
else:
return [False, "Not Connected"]
def DeleteFile(self, theid):
if self.Connected:
try:
self.Cursor.execute("DELETE FROM maxfiles WHERE id=%s" % (theid))
return True
except:
return [False, TBWrite()]
else:
return [False, "Not Connected"]
def RollBackChanges(self, yayorney):
if self.Commited == True:
return [False,"Data already commited, better luck next time"]
if self.Connected:
if yayorney:
try:
self.db.rollback()
return True
except:
return [False, TBWrite()]
else:
return [False, "Not Connected"]
def ReConnect(self, server, username, password, database):
self.Connected = False
self.db = None
self.Cursor = None
self.Commited = True
try:
self.db = mys.connect(host=server, user=username, passwd=password, db=database)
self.Cursor = self.db.cursor()
self.Connected = True
except:
return [False, TBWrite()]
if __name__ == "__main__":
con = MaxFileSaver("localhost", "root", "daveRoot", "mymaxfiles")
print con.InsertFile("C:\\\\With Any luck this will work.max")
print con.CommitChanges(True)
for i in con.GetFiles():
print i
print con.DeleteFile("14")
print con.SetFile("23", "C:\\\\SomeNewFile")
print con.CommitChanges(True)
specxor
10-22-2007, 01:46 PM
Hi guys,
Just wrote a new com class for MySQL connections. It works well and is simple to implement.
Here is the code:
"""
MySql com class, provides basic connection to MySQL across com.
Crafted By,
David Mackenzie
Notes:
-All errors are handled, if an exception is caught, a list is returned as [False, the traceback]
-Requires MySQLdb, http://sourceforge.net/projects/mysql-python
-If you get any tracebacks please post them or send them to me!
-I pulled this code from a larger implementation im working on so there may be some bugs, although there should not.
Max Usage:
>> a = createOLEObject "DavesTools.ComSql"
<OLEObject:DavesTools.ComSql>
>> a.Connect "localhost" "root" "daveRoot" "mymaxfiles"
true
>> a.Execute("SELECT files FROM maxfiles WHERE id=3")
true
>> a.Fetch()
SafeArrayWrapper #("Somemaxfile.max") #(0)
"""
import MySQLdb as mys
import traceback
class ComSql:
"""Com interface for parsing SQL commands."""
_public_methods_ = ['GetCommited',
'GetConnected',
'Connect',
'Execute',
'Fetch',
'RollBack',
'Commit']
_reg_progid_ = 'DavesTools.ComSql'
_reg_clsid_ = '{3B165F3B-6E90-4E1B-AA34-D6B3E51C9115}'
def __init__(self):
self.Connected = False
self.Commited = True
self.Cursor = None
self.db = None
def GetCommited(self):
return self.Commited
def GetConnected(self):
return self.Connected
def Connect(self, server, username, password, database):
"""Connect to the database"""
try:
self.db = mys.connect(host=server, user=username, passwd=password, db=database)
self.Cursor = self.db.cursor()
self.Connected = True
self.Commited = True
return True
except:
self.Connected = False
self.Commited = True
self.Cursor = None
self.db = None
return [False, self.__sqlerror()]
def Execute(self, command):
"""Execute the parsed command."""
if self.Connected:
try:
self.Cursor.execute(command)
self.Commited = False
return True
except:
return [False, self.__sqlerror()]
else:
return [False, "Not Connected"]
def Fetch(self):
"""Return Data from the db, the appropiate command should had have been parsed to execute before hand"""
if self.Connected:
try:
return self.Cursor.fetchall()
except:
return [False, self.__sqlerror()]
else:
return [False, "Not Connected"]
def RollBack(self):
"""Roll back any un-commited changes"""
if self.Commited:
return [False, "Data already commited"]
else:
if self.Connected:
try:
self.db.rollback()
return True
except:
return [False, self.__sqlerror()]
else:
return [False, self.__sqlerror()]
def Commit(self):
"""Commit changes to database"""
if self.Connected:
try:
if self.Commited == False:
self.db.commit()
self.Commited = True
return True
except:
return [False, self.__sqlerror()]
else:
return [False, self.__sqlerror()]
def __sqlerror(self):
return traceback.format_exc()
if __name__ == "__main__":
TESTING = False
if TESTING:
print "Testing\n"
con = ComSql()
print "Connect:\n\t", con.Connect("localhost", "root", "daveRoot", "mymaxfiles")
print "Execute:\n\t", con.Execute("INSERT INTO maxfiles (files) values('C:\\\\SomeNewFile.max')")
print "Commint:\n\t", con.Commit()
print "Execute:\n\t", con.Execute("SELECT * FROM maxfiles")
print "Fetching:\n\t", con.Fetch()
print "\nDone"
else:
print "Registering COM server..."
import win32com.server.register
win32com.server.register.UseCommandLine(ComSql)
Cheers
Dave
TheIvIaxx
11-06-2007, 12:01 AM
I'm getting some wierd garbage collection errors when pairing python and max. So my script basically sends the "loadmaxfile" command with a file, max opens it, run a maxscript on it, and return a list of strings. then moves on to another file. simple enough right?
Well after about 3-4 files, max throws this wierd error:
"Unknown error occured during garbage collection. If you see this message frequently, restart max." or something to that extent. I put the gc() in my maxscript hoping that would fix it, but no luck.
Am i not doing something here? My python stuff is pretty simple:
pyMax = win32com.client.Dispatch("MAX.Application.8")
pyMax._FlagAsMethod("loadMaxFile")
pyMax._FlagAsMethod("RenderItem")
...
for z in names:
print "Building object..."
newItem = item(z)
print "Object built, Loading into max..."
try:
pyMax.loadMaxFile("Z:\XXX" + z.replace("/", "\\"))
except pywintypes.com_error, e:
print e[1]
print "Rendering Item..."
renderedItems = []
try:
renderedItems = pyMax.RenderItem()
newItem.dbInsert(renderedItems)
except pywintypes.com_error, e:
print e[1]
print "Success, moving on..."
"item()" is a python object which does some DB stuff.
"RenderItem()" is the maxscript being run.
Thanks
RustyKnight
11-06-2007, 12:39 AM
I'm getting some wierd garbage collection errors when pairing python and max. So my script basically sends the "loadmaxfile" command with a file, max opens it, run a maxscript on it, and return a list of strings. then moves on to another file. simple enough right?
Well after about 3-4 files, max throws this wierd error:
"Unknown error occured during garbage collection. If you see this message frequently, restart max." or something to that extent. I put the gc() in my maxscript hoping that would fix it, but no luck.
Am i not doing something here? My python stuff is pretty simple:
pyMax = win32com.client.Dispatch("MAX.Application.8")
pyMax._FlagAsMethod("loadMaxFile")
pyMax._FlagAsMethod("RenderItem")
...
for z in names:
print "Building object..."
newItem = item(z)
print "Object built, Loading into max..."
try:
pyMax.loadMaxFile("Z:\XXX" + z.replace("/", "\\"))
except pywintypes.com_error, e:
print e[1]
print "Rendering Item..."
renderedItems = []
try:
renderedItems = pyMax.RenderItem()
newItem.dbInsert(renderedItems)
except pywintypes.com_error, e:
print e[1]
print "Success, moving on..."
"item()" is a python object which does some DB stuff.
"RenderItem()" is the maxscript being run.
ThanksI had a simular issue recently (not with the com bridge, but with max). I may be totally off the mark, but...it may have something to do with the inital heap settings for maxscript.
Go to Customize -> Preferences -> Maxscript (tab) and increase the maxscript memory to a larger amount...about 60-70meg should do the trick. Then try again.
At least you will know if it is a max issue or a com issue pretty quickly.
Also, play around the amount of memory as well till you find a setting you are comfortable with.
Hope it helps
Shane
specxor
11-06-2007, 09:08 AM
Hi Brett,
I have a similar setup for keeping asset library's in order, which essentially recursively goes through a library and updates the database where it needs to. I did notice that the machine I run it on has the max script heap size set to 128mb, so maybe Shane is on to something, I might try lowering the heap size and see what happens.
I'm interested to here how you go...
Cheers
Dave
TheIvIaxx
11-06-2007, 05:57 PM
ok, i set it to 128mb and it seemed to work pretty good. Due to some bugs with my script it will sometimes blow up max. But upping the heap size let me get through 12+ without issue which is way more than before. I will keep tweaking it and let you know what i find.
Thanks again
TheIvIaxx
11-06-2007, 11:28 PM
OK, so i removed the gc() call in my script and upped my heap to 256MB and its working much better now. Thanks for the help guys.
lechoo
12-18-2007, 11:59 AM
What should I do if I have two instances of 3ds max launched, I want to control one of them with python and choose which one? Right now only max that was started first works as COM Server.
ehulser
12-19-2007, 04:41 AM
Hey guys,
I just finished up the first version of this DLL for 3dsMax (still pretty rough) that we're going to start using here at Blur...pretty much it embeds python for use inside of MAXScript, opening up all the modules that exist in python directly. There are some example scripts on how its used, but its relatively simple - you import your module, and work with with it as if you were in python.
re = python.import "re"
m = re.match "[a-zA-Z]*" "Test test test"
if ( m != undefined ) then ( print (m.group()) ) -- prints "Test"
etc.
More examples in the DLL. We're working (still) on getting BlurBeta running where everything will be open source, but until that gets up, I have the *.zip file with the DLL and would love some feedback on how its working, just no where to throw the zip. If anyone has a mirror, I can email the file to you and upload it so others can download. Otherwise, email me if you want the DLL and I'll send it to you.
Thanks!
Eric Hulser
eric@blur.com
Tools Developer
Blur Studio
martinB
12-19-2007, 10:20 AM
I just finished up the first version of this DLL for 3dsMax (still pretty rough) that we're going to start using here at Blur...pretty much it embeds python for use inside of MAXScript, opening up all the modules that exist in python directly.
That is pretty cool! I can wait for your final release but if that is out, make sure to let us know! Directly connecting Python to MAXScript will make a bunch of people very happy over here.
Cheers!
-- MartinB
ypuech
12-19-2007, 12:27 PM
I just finished up the first version of this DLL for 3dsMax (still pretty rough) that we're going to start using here at Blur....pretty much it embeds python for use inside of MAXScript
Being able to use Python inside Max is a great new stuff and will make me learn Python much faster!
If anyone has a mirror, I can email the file to you and upload it so others can download. Otherwise, email me if you want the DLL and I'll send it to you.
You can contact David Baker of maxplugins.de (he is on CGtalk forums). He can offer a subdomain with space to host your plugins and web stuff for free.
Not sure if this is going to create a double post, if so please delete.
If you want I can put it on on http://paulneale.com, just mail it to
paul@paulneale.com
Hey guys,
I just finished up the first version of this DLL for 3dsMax (still pretty rough) that we're going to start using here at Blur...pretty much it embeds python for use inside of MAXScript, opening up all the modules that exist in python directly. There are some example scripts on how its used, but its relatively simple - you import your module, and work with with it as if you were in python.
re = python.import "re"
m = re.match "[a-zA-Z]*" "Test test test"
if ( m != undefined ) then ( print (m.group()) ) -- prints "Test"
etc.
More examples in the DLL. We're working (still) on getting BlurBeta running where everything will be open source, but until that gets up, I have the *.zip file with the DLL and would love some feedback on how its working, just no where to throw the zip. If anyone has a mirror, I can email the file to you and upload it so others can download. Otherwise, email me if you want the DLL and I'll send it to you.
Thanks!
Eric Hulser
eric@blur.com (http://forums.cgsociety.org/eric@blur.com)
Tools Developer
Blur Studio
There is now a link to the Python plugin from Blur Studios on my site at http://paulneale.com/
It is the second news article currently on the home page.
ehulser
12-19-2007, 10:41 PM
Thanks a lot for hosting it Paul, hopefully you guys will find it useful.
I'll keep everyone posted on updates, please let me know of any bugs/issues, and I'll also keep everyone up to date on the BlurBeta status
Thanks!
Thanks for creating it and thanks to Blur for allowing you to share it. Once you have BLur Beta back up and running let me know and I will pull it down from my site and link up to Blur Beta. Just email me updates and I will try and get them up there right away.
ypuech
12-20-2007, 01:01 PM
Thanks Eric and Paul.
If I understand, the goal of this DLX is to baccess Python modules in MAXScript like the dotNet wrapper that allow the use of .NET Framework. We'll be able to also access our own Python modules and we'll develop even more powerful tools.
So I have to learn Python now...
TheIvIaxx
12-20-2007, 05:23 PM
this is awesome. Thanks Eric and Paul! Im sure this will make many, many people happy
So I have to learn Python now...
you say that like it's a bad thing :thumbsup:
ypuech
12-20-2007, 07:32 PM
you say that like it's a bad thing :thumbsup:
I know that I have to learn Python to improve my skills because as I want to work in a real 3D production environment in the future, Python is mandatory now.
Don't worry, there's no problem with learning a new language :) but I know that Python is a large development framework and there's many interesting things to learn.
Kramsurfer
12-21-2007, 09:51 PM
WOW... amazing... Loving it.... WOW again.. sooo easy... soo sweet....
Can not thank you enough...
cgBartosz
01-07-2008, 07:52 AM
Hi,
Thank you, ehulser (http://forums.cgsociety.org/member.php?u=38202) ,for sharing your blurPython.dlx. It seems to be a great tool. Maybe, you can help me with situation I'm having. I did all steps neccessary according to the read me file from plugin package. Command, python.import works for "sys" module but anything else returns undefined value.
Another question would be about 3dsmax COM/DCOM server and win32com.
It works just fine and it would be great if there is any possibility of getting progID of each max instance running. Do you know how to obtain it ?
Thanks !
ehulser
01-08-2008, 07:14 PM
cgBartosz - do you have an example of what was not working? I'm thinking it might be related to a problem I noticed recently - the way MAXScript passes variables back and forth between script and C++ is through the Name class instance, which is case insensitive. Which means, the first instance of a name created is the one stored, and since Python is case sensitive, this causes a problem. So, something like:
sys = python.import "sys"
sys.Path -- would cause an error, because the path variable is all lowercase
sys.path -- will still cause an error, because Max's internal conversion already has the
-- name value as an uppercase p
I've gotten around this in a newer version of the plugin, which I'm going to send to Paul to host, but could explain some discrepencies when accessing information. In terms of importing though, that should be case sensitive since it is string values and not names. If you send me an example I can look through it.
Also, some of the examples I had in the python zip about strings are apparently deprecated in python now (thanks to Keith Morrison for pointing this out):
ref: The following list of functions are also defined as methods of string and Unicode objects; see ``String Methods'' (section 3.6.1 (http://docs.python.org/lib/string-methods.html#string-methods)) for more information on those. You should consider these functions as deprecated, although they will not be removed until Python 3.0.
http://docs.python.org/lib/node42.html
So, just be wary of Python changes when building tools reliant on Python modules.
cgBartosz
01-08-2008, 09:16 PM
cgBartosz - do you have an example of what was not working?
Importing "sys" module works, and importing "os" module returns an undefined value.
This is what I get in the listener after evaluating regex.ms sample script
undefined
undefined
-- Error occurred in anonymous codeblock
-- Frame:
-- split: undefined
-- normpath: undefined
-- splitList: undefined
-- newnorm: undefined
-- Unknown property: "path" in undefined
print os
undefined
undefined
print str
undefined
undefined
... conversation with listener
python.import "sys"
<module 'sys' (built-in)>
print sys.version
"2.4.3 (#69, Jul 13 2006, 15:36:15) [MSC v.1400 32 bit (Intel)]"
"2.4.3 (#69, Jul 13 2006, 15:36:15) [MSC v.1400 32 bit (Intel)]"
['C:\\Python25', '', 'E:\\3dsmax9']
['C:\\Python25', '', 'E:\\3dsmax9']
<module 'sys' (built-in)>
<module 'sys' (built-in)>
global os = python.import "os"
undefined
global str = python.import "string"
undefined
python.import "os"
undefined
from python interpreter...
IDLE 1.2.1
>>> import sys
>>> print sys.path
['C:\\Python25\\Lib\\idlelib', ... 'C:\\Python25\\lib\\site-packages\\']
>>> print sys.version
2.5.1 (r251:54863, Apr 18 2007, 08:51:08) [MSC v.1310 32 bit (Intel)]
>>>
thatoneguy
01-09-2008, 10:26 PM
Could someone do something reeeaalllly basic for me?
I see a lot of Python -> Max stuff. But how do I make the round trip? I'm still trying to wrap my mind around a "hello world" script.
I want to send data from max. Let's just say an array.
[1,2,3] -> OLE -> Python. Have Python add 1 to each value and then reload it in Max.
What does that code look like?
ehulser
01-10-2008, 08:55 PM
cgBartosz:
Thats weird, I haven't run into that. Has anyone else? Try just running this in your listener and see if it returns undefined:
os = python.import "os"
I get back the os module, from which I can run path functions, etc.:
os = python.import "os"
<module 'os' from 'C:\python24\Lib\os.pyc'>
os.path.split
<function split at 0x10303BB0>
thatoneguy:
Not exactly sure where you are going with this/why you'd need it - if the idea is that you'd have an external python library to manipulate data that you want supply from max and get it back, it'd go like:
pymodule.py:
def plusone( valueList ):
for value in valueList:
value += 1
return valueLIst
msscript.ms:
pymodule = python.import "pymodule"
arr = #( 1,2,3 )
arr2 = pymodule.plusone( arr )
print arr2
----- Result of Print ---------
2
3
4
ehulser
01-10-2008, 08:58 PM
cgBartosz:
Also, what version of Python do you have? Make sure that you can import the os module in Python itself - you can only import modules that exist within your Python install
ehulser, I got the update, I will post it as soon as I'm back to my office.
Kramsurfer
01-11-2008, 01:00 AM
Fun with new python plugin.
In a startup script; initalize oddly named python and DotNet controls and data classes.
Write short script with simple UI with dotnet / MSX elements, data storage and malipulation using Dotnet data classes, python file access and MaxScript for Node access. Written with minimal line documentation.
Hand to co-worker asking what's wrong... ha ha ha...
focomoso
01-11-2008, 08:23 AM
It probably sounds sad, but I just got the first post example running and I felt a little thrill of excitement.
I'm going to buy you a round whenever I see you David. :beer:
Woo hoo! Just got that same thrill.
Teirz
01-11-2008, 01:27 PM
Hi,
Again thanks ehulser for sharing the dlx. I'm having the same problem like what cgBartosz has encountered.
I'm currently running python 2.5.1.
It seems like you can import all the built in modules without any error within max. But when you try to import other library it just return undefined as thou it can't find the path.
However within python there's no problem importing using:
>>> import sys
>>> print sys.version
2.5.1 (r251:54863, Apr 18 2007, 08:51:08) [MSC v.1310 32 bit (Intel)]
>>> import os
>>> os
<module 'os' from 'C:\Python25\lib\os.pyc'>
Thanks again for sharing :).
RustyKnight
01-11-2008, 11:29 PM
Could someone do something reeeaalllly basic for me?
I see a lot of Python -> Max stuff. But how do I make the round trip? I'm still trying to wrap my mind around a "hello world" script.
I want to send data from max. Let's just say an array.
[1,2,3] -> OLE -> Python. Have Python add 1 to each value and then reload it in Max.
What does that code look like?I'm sure I posted a reply to this a few days ago, oh well...
Basically, I've not tried this under python, but have been investigating the possibility using Java. This is what I've found...
Max can talk to "OLE Auutomation Servers" ... commonly known as COM servers...
So, in order to get this to work, you will need to create your own COM server, register it under windows and, using Max's "OLE Client" functions, connect and communicate with it...
There is some sample code on the install disk, but you will also want to look up "OLE Client" and "Running the OLE Demo" for more info.
I hope this helps
Shane
Python plugin has been updated on my site.
Teirz
01-13-2008, 08:48 AM
Ok i have tried with python 2.4.4 and it seems to work fine now without any problem on importing modules.
I guess that the current python plugins is not compatible with 2.5.1. With 2.5.1 the sys version will always revert back to the built-in version which is 2.4.3 (#69) instead of the following result that i'm getting from max with 2.4.4.
sys = python.import "sys"
<module 'sys' (built-in)>
sys.version
"2.4.4 (#71, Oct 18 2006, 08:34:43) [MSC v.1310 32 bit (Intel)]"
os = python.import "os"
<module 'os' from 'C:\Python24\Lib\os.py'>
Not sure if i'm right on this. Hope it helps on anyone else having the same problem. But at least i get to start working on more python tools.
ehulser
01-14-2008, 10:21 PM
This probably has to do with the plugin being compiled with Python 2.4 libs. Thats the version we're running and the code was compiled for - do you have both python versions installed? Try flushing the sys.path variable to remap to c:/Python25 instead of 24
ehulser
01-14-2008, 10:22 PM
which reminds me - I still haven't mapped setting attributes...will have to get on that...
for instance, cant do this:
sys = python.import "sys"
sys.path = #() -- That'll crash...though it shouldn't
Teirz
01-15-2008, 03:59 AM
I have both 2.5.1 and 2.4.4 installed. And yup can't really remap for now as it will just return
-- Unknown property: "path" in <module 'sys' (built-in)>
I was trying to use MySQLdb module with blurPython in max. But seems like the connection string can't map correctly yet too. Just to let you know before hand :)
This works in python IDLE
import MySQLdb
MySQLdb.connect(host="localhost",user="root",passwd="Mypassword",db="MyDB")
while this doesn't in maxscript
pysql = python.import "MySQLdb"
<module 'MySQLdb' from 'C:\Python24\lib\site-packages\MySQLdb\__init__.pyc'>
pysql.connect
<function Connect at 0x103E0030>
conn = pysql.connect(host="localhost",user="root",passwd="Mypassword",db="MyDB")
-- Syntax error: at ),, expected <factor>
-- In line: conn = pysql.connect(host="localhost",u
Not sure if i'm doing something wrong thou.
thatoneguy
01-15-2008, 10:21 PM
Yeah MySQLdb was the big reason I wanted python integration more seamless without using ODBC and OLE.
specxor
01-16-2008, 11:40 AM
Hi Guys,
Having had just returned from holidays this is awesome, I definitely have to shout Eric some beers! awesome work! I have only had a quick chance to play with it so far but it looks very impressive.. A quick question, what is the likely hood of a 64bit build?
Again thanks to Eric and blur for sharing this with us for those of us who have large and complex python based pipelines this will be fantastic to better integrate max.... Thanks to Paul for hosting as well!
Cheers
Dave
ehulser
01-16-2008, 08:42 PM
Teirz:
Keep in mind you are actually running MAXScript code that wraps Python code, so it still goes through the MAXScript interpreter. In MAXScript, you can't call a function this way:
pysql = python.import "MySQLdb"
pysql.connect( host = "localhost", user = "root", passwd = "Mypassword", db = "MyDB" )
It has to be in proper maxscript syntax:
pysql = python.import "MySQLdb"
pysql.connect host:"localhost" user:"root" passwd:"Mypassword" db:"Mydb"
right now I don't have it mapping optional variables though, so for right now you cant pass in optional variables like that, this should work for right now though:
pysql = python.import "MySQLdb"
pysql.connect "localhost" "root" "Mypassword" "Mydb"
Important thing though, and I know this is kinda confusing, you still have to follow MAXScript syntax rules even though its executing Python methods.
specxor:
Hope it helps, we have a Python based pipe and are hoping this'll help tie it all together too. I'll include a x64 build in the next release, also a max8 release. We've needed both here also.
So, to recap:
Known issues:
No setattr implemented
No optional method variables implemented
Anything else?
Teirz
01-17-2008, 03:56 AM
Thanks Eric again for clearing my confusion. It all works perfectly now, just like a turbo button for max scripting. Connecting to database is so much cleaner and totally no problem getting the cursor to work. I will try to feedback if there's any other issue as i am still working on the python based pipe for my studio.
By the way, i'm using this plugin with Max 2008. So we can probably assume that this plugin is ready for max 2008 as well. And the best thing is that at least i won't have to worry the complains from any Maya TD that they can't use python as easy in max now.
I would love to hear a brief description on what you are using Python for in your pipelines and what you are doing with it. I'm slowely writting the spec for a pipeline and wonder where others have gone before me.
ehulser
01-17-2008, 05:54 PM
This plugin should work for max9+ until they switch compilers like from max8 to max9. (theoretically) Though the plugin itself is simple and should easily translate to future versions. I'm hoping this should bridge a large gap in 3dsMax integration as a lot of studio's I know of use Python in their pipeline.
We started using Python when we added XSI into our pipeline as it was the most powerful of the scripting languages available for XSI, and have since expanded much of our pipe to using Python as the core. Since we have to support 3dsMax and XSI, we keep as much information that we can share and keep in a single library as we can, so naming conventions, path templates, XML formatting, and eventually connections into production tracking and asset management would run as separate python modules that we could now directly incorporate into 3dsMax. Before, we had to duplicate the functionality through a DLL or MAXScript library and it became a pain to manage.
Mostly, I'm just lazy.
focomoso
01-17-2008, 09:24 PM
We're porting a tool to help with lip syncing from maxScript to python. Our own version of papagayo that sits just below the time line, if anyone's familiar with that program. Python is siginifigantly faster at parsing the huge dictionary files and so far, wxPython is much faster than maxScript at drawing our (probably too complicated) interface. If it goes well, we'll be porting all of our tools to python.
Teirz
01-18-2008, 03:38 AM
We are still developing it to replace our old pipe for TV series. As my current main focus is TV series which normally has a very tight schedule, e.g. 1-4 episode per month depends on the budget and animation length, by having a proper customize asset management and production tracking system is very important to us. And sometimes we need to swap between maya and max, so it's more practical to share the data/scripts and any other data e.g. selections sets, enforced naming convention etc to keep the consistantcy without the need to write some scripts twice. Even the XML formatting is extremely useful with the new version of FCP. It's quite possible that i will be porting all the in house tools to python so those who are more familiar with maya can just duplicate the same function without wasting much development time.
Another thing that i'm working on with python is the asset tracking. Whatever max9/2008 having now is still not as friendly for production. For example, there's a lot of time i need to know this asset maxfile have merged in which model, with which material library loaded, with which rig, and which lighting master file, and done by which guy. I don't like the idea of xref as there's too much limitation, and thanks to PEN (yup here must credit you for your batch processing scripts :)). Keeping track of these without a proper system would really drive someone crazy.
The last thing i wanna hear from my EP is "Which idiot has name this file as EpXX_ScXX_ShXXX_final_final which is not FINAL! Where's the freaking latest file!"
specxor
01-19-2008, 06:06 AM
Hi Paul,
Here is a quick description of what we are currently using python for in our pipeline...
We are using python in our pipeline to mange assets, task assignment, render passes, project creation and project management. Our artists use a standalone application written entirely in python to manage all aspects of the job. We are also experimenting with using python to dynamically create our scene and render files.
All of our asset management is database driven, we use a custom server to handle task delegation, new asset creation and the creation of new projects, scenes and shots. Max files and file structures are dynamically created to conform to our in-house conventions.
We (I) have also been developing a replacement to back burner that will support multiple packages, generate previews and a bunch of other things that are pretty cool ;).
Cheers
Dave
Teirz
01-19-2008, 08:47 AM
We are using python in our pipeline to mange assets, task assignment, render passes, project creation and project management. Our artists use a standalone application written entirely in python to manage all aspects of the job. We are also experimenting with using python to dynamically create our scene and render files.
All of our asset management is database driven, we use a custom server to handle task delegation, new asset creation and the creation of new projects, scenes and shots. Max files and file structures are dynamically created to conform to our in-house conventions.
Hi Dave,
It seems like everyone is going towards the same direction.
And i believe that the database you are running at had a gigantic and complex setup, at least while reference to what i'm still working on now, cause you have a much complicated pipe there.
I'm interested on how you handle the artist on file managing. Does your artist create all the asset files thru your system, meaning they are totally isolate from e.g. window explorer to create files, or even the default save button in any application that's involved in the pipe.
specxor
01-22-2008, 10:48 AM
Hi Teirz,
It does seem like everyone or allot of studios are going down the python route... With assets, we have a mix between our software handling files but still allowing artists to be able to get at files manually should they need it.
We have replaced all of the standard save, save selected, export etc.. with our own tools that takes over from the user and creates entries in the database, all files are saved in there correct location based on the type of asset they are, for instance if it was a character or prop etc.. The software handles all of this, we found its much easier if you keep a logical file structure so if artists need to for what ever reason they can still find what they are looking for with out to much effort.
Hope that helped..
Cheers
Dave
That is great info, thanks. I have done the same but I have done it with MXS and XML only at this point. Since I do most of my development for smaller companies these days I don't always get the time to develop larger tools and systems. I'm looking at creating a flexible tracking system that I can impliment with clients as they need it instead of just reinventing the wheel each time.
thatoneguy
01-22-2008, 07:16 PM
We're developing a system which:
Keeps track of every job and what its status is.
Each deliverable's version/revision number.
Is tied into our time card software to keep track of bids and available time.
Keeps naming conventions consistant.
And in the future will develop front ends for the client to actually interact with the deliverable making limited changes through a python/php interface.
We also want to in the near future open up our internal pipeline status in a limited way to clients so they can review the status of their job and check in on the latest deliverables in a more transparent manner.
And a bunch of other cool stuff which is all on the drawing board.
Edit: We also have a lot of asset tracking with thousands of objects which need to be called on nearly instantly we're considering moving all of this to a database from CSV files.
loocas
02-07-2008, 08:46 PM
Thank you so much for the DLX, ehulser :buttrock:
You're the man! :thumbsup:
vScourge
02-23-2008, 01:55 AM
My GDC talk "Python for Technical Artists" was today. I've posted my slides and code sample files here:
http://www.volition-inc.com/gdc
The Python examples include several scripts in a few Tech Art-oriented categories:
- Data mining (large XML files)
- Data Serialization/Persistence
- Screen scraping
- Textures
- Databases (MySQL, etc)
- Windows COM
The COM group includes examples on driving 3ds Max and Maya in various ways from outside of those apps, using Python. There's a fun example that uses a 360 controller to fly a camera around a 3ds Max scene and place world objects on a landscape, with just a few lines of embedded MaxScript.
Check out the examples, let me know what you think.
martinB
02-23-2008, 08:14 AM
Awesome, Adam. Thanks a lot for posting this!
-- MartinB
loocas
02-23-2008, 09:21 AM
Thanks a lot vScourge, I really appretiate sharing this with us! :buttrock:
specxor
02-24-2008, 10:42 PM
Thanks Adam this is really good stuff, I especially like work you have done to parent a wx.Frame to max window, this will undoubtedly make some of tools of ours look cleaner and allot more native.
Nice work!
Cheers
Dave
Kermit
02-25-2008, 06:12 PM
hi all,
first, thx all for sahre your experience, yours tips and your code
it's very really interessant
ehulser : have you possibility for compile a x64 release ?
thx again
Kermit
vScourge
02-25-2008, 08:00 PM
Thanks Adam this is really good stuff, I especially like work you have done to parent a wx.Frame to max window, this will undoubtedly make some of tools of ours look cleaner and allot more native.
Very welcome.
I picked up that window-linking trickery from Aloys Baillet from Animal Logic. He posted an example of that in this XSI-related blog (http://www.xsi-blog.com/archives/138) he posted, so hats off to him. I just tweaked it to work with 3ds Max instead.
Another cool thing that isn't actually shown-off in my example scripts is the ability to create modal dialogs (warning pop-ups, etc) from your external Python script, so that the 3ds Max window is properly disabled as well. There's code to do that via the "show_modal_dialog" class method in the "MaxComClasses.py" file, but the examples don't call it anywhere.
You might also notice some commented-out code in that file that was the start of my attempt to create a bi-directional COM setup that would allow 3ds Max to instigate/call code inside that same Python script. Meaning, you could have MaxScript-ed callbacks that actually tell the Python script to update its UI or whatever. As it stands, with Max being the COM server and Python the client, you can only use Python to instigate an event, not vice-versa. I didn't get to work much on the bi-directional COM thing before GDC, but hope to play with it more soon.
In any case, I'd love to hear more examples of how people use stuff like this.
TheIvIaxx
02-29-2008, 07:19 AM
We have been using this for photoshop. because we all know how fun scripting is in PS :banghead:
RustyKnight
03-01-2008, 01:03 AM
Very welcome.
You might also notice some commented-out code in that file that was the start of my attempt to create a bi-directional COM setup that would allow 3ds Max to instigate/call code inside that same Python script. Meaning, you could have MaxScript-ed callbacks that actually tell the Python script to update its UI or whatever. As it stands, with Max being the COM server and Python the client, you can only use Python to instigate an event, not vice-versa. I didn't get to work much on the bi-directional COM thing before GDC, but hope to play with it more soon.That's quote interesting...
I had a very quick look at this and they only way I could find that would make this work was to create a COM server of my own and have max connect to it. The original idea was to allow the app to talk to max and max to talk back within the same context, but I havn't yet quite gotten around to setting it up and testing it.
I'd be interested in know how you intended to achieve this
Cheers
Shane
specxor
03-25-2008, 05:35 AM
Hi Guys,
I wrote some a class for working with back burner a couple weekends ago, at the moment I have the ability to read data from the back burner manager, I am working on seting values and adding new job etc now.
Thought some of you who are still using back burner might find this useful. I have used it to create Web interfaces and SMS alerts since writing it.
I have some more code that I will post soon (depending on how busy I am) that implements "Events" that can be used as callbacks. For example when a render fails it triggers an event (that's how I implemented SMS alerts).
In the zip is the source and a pdf with simple (very simple) flow chart showing the data structure.
Anyways, if you find any bugs or have any suggestions just post them.
Cheers
Dave
specxor
03-28-2008, 01:40 PM
Hi guys,
I wrote a simple demo to show the usage of pyBurner, basically a dumbed down version of the Back Burner Monitor. I have attached a screen shot, I will upload the source tomorrow.
Screen Cap:
http://www.daveandgoliath.com/gol_images/cgtalk/pyBurn-ScreenCap.jpg
Cheers
Dave
loocas
04-20-2008, 10:46 PM
I gotta ask.
Any news on the blurPython.dlx recompile for x64 as well as Max 2009 x86/x64? Would be so much appretiated! :bowdown:
specxor
04-21-2008, 12:40 AM
Yeah I have been hanging out for an x64 build as well..
Cheers
Dave
erilaz
04-21-2008, 03:07 AM
We have been using this for photoshop. because we all know how fun scripting is in PS :banghead:
Can you elaborate on using python for photoshop? Sounds really useful!
Kermit
04-21-2008, 07:54 AM
hi,
somes infos for use python with photoshop
http://www.int80.org/pycs/
Kermit
Kramsurfer
04-21-2008, 04:57 PM
Wow. Thanks for the Photoshop link, that's killer... I think I'll just delete all my .jsx files.. ha ha...
ehulser
04-21-2008, 07:23 PM
hey guys, sorry its been a while - I've been busy with other things and will still be busy for a little while, but we're slowly trying to integrate python throughout the studio for all our production tracking needs, with that will come much more improvements to the Max DLL's. Pretty much, right now I'm waiting on Python for x64 libs to link to create a x64 bit version for max, we don't have Max 2009 yet, so I don't have any of the SDK changes or an install of the latest compiler so hopefully i will get to that sometime in the summer.
sorry!
erilaz
04-28-2008, 03:41 AM
Hi guys,
I've created a cgWiki entry to start consolidating the examples and discussion presented here:
http://wiki.cgsociety.org/index.php/MAXScript_and_Python
I'm also in the process of setting one up for dotNet.
If you can see concise ways to add the code examples or correct and expand on what i've said, please feel free to go nuts. :D
The two links for the articles extend from the main Maxscript article here:
http://wiki.cgsociety.org/index.php/Maxscript
specxor
04-28-2008, 05:07 AM
Hi Martin,
The wiki page is great idea I will add some examples later this week.
Cheers
Dave
erilaz
04-29-2008, 01:49 PM
Hi Martin,
The wiki page is great idea I will add some examples later this week.
Cheers
Dave
Thanks Dave. I just bought Mark Lutz's books today to finally get my head around the whole thing properly. :)
specxor
04-30-2008, 12:59 AM
Mark Lutz's books are really good I have two of them on my desk all the time.. I also like Core Python by Wesley Chun.
Cheers
Dave
CyHiSo
05-01-2008, 11:50 AM
Hi,everybody!
I have just tried to make smth in max via python but when i try to dispatch max application i get something like this:
code in python:
import win32com.client
conn = win32com.client.Dispatch("MAX.Application.8")
.....
and when i evaluate it i get:
Traceback (most recent call last):
File "C:/Python25/1", line 5, in <module>
conn = win32com.client.Dispatch("MAX.Application.8")
File "C:\Python25\Lib\site-packages\win32com\client\__init__.py", line 95, in Dispatch
dispatch, userName = dynamic._GetGoodDispatchAndUserName(dispatch,userName,clsctx)
File "C:\Python25\Lib\site-packages\win32com\client\dynamic.py", line 98, in _GetGoodDispatchAndUserName
return (_GetGoodDispatch(IDispatch, clsctx), userName)
File "C:\Python25\Lib\site-packages\win32com\client\dynamic.py", line 78, in _GetGoodDispatch
IDispatch = pythoncom.CoCreateInstance(IDispatch, None, clsctx, pythoncom.IID_IDispatch)
com_error: (-2147221005, '\xcd\xe5\xe4\xee\xef\xf3\xf1\xf2\xe8\xec\xe0\xff \xf1\xf2\xf0\xee\xea\xe0 \xf1 \xf3\xea\xe0\xe7\xe0\xed\xe8\xe5\xec \xea\xeb\xe0\xf1\xf1\xe0', None, None)
i ran it under python 2.5 with win32 module installed
what am i doing wrong??
specxor
05-02-2008, 01:32 AM
Hi CyHiSo,
Did you register the com service from max?
Cheers
Dave
CyHiSo
05-02-2008, 06:46 PM
Hi CyHiSo,
Did you register the com service from max?
Cheers
Dave
yes.i ran that script. but, it seems to me that there is some other problem.i can't understand why python returns error when im trying to dispatch it with
conn = win32com.client.Dispatch("MAX.Application.8")?
vScourge
05-02-2008, 10:06 PM
Are you running Vista bychance?
If so, you might try disabling User Account Control (UAC). That's a known source of mysterious COM failures.
mberglund
05-05-2008, 08:41 PM
Has anyone tried getting the Com to work with mutliple instances of max running?
CyHiSo
05-05-2008, 09:35 PM
Are you running Vista bychance?
If so, you might try disabling User Account Control (UAC). That's a known source of mysterious COM failures.
No.I'm runnin' XP SP2
specxor
05-06-2008, 12:22 AM
Has anyone tried getting the Com to work with mutliple instances of max running?
Yes, it only works when max is calling a COM object. If you are calling maxes com server the most recently opened max takes focus, I have not found a solution to this problem (yet).
Cheers
Dave
specxor
05-06-2008, 12:25 AM
No.I'm runnin' XP SP2
Did you register the maxes COM server while logged in with Admin rights? I have found that if you register the com server without admin rights you will (may) get an error.
Cheers
Dave
erilaz
05-14-2008, 03:11 AM
I'm going to put my hand up to claim total ignorance about how binary data is parsed, so take this question in that light:
I'm looking to mine .max files for their internal data (such as textures, poly counts etc) so I can set up a file browser that gives a detailed description of the contents.
Has anyone done this before? My knowledge of file reads has been limited to ascii data in the past, so i'm trying to work out if I need to use some sort of struct read or unpack to bring in the max file information to search and pull out the correct values. That's pretty much where my brick wall starts!
This is a purely external python project. I want to be able to mine max files without accessing the max runtime at all.
loocas
05-14-2008, 01:48 PM
I'm going to put my hand up to claim total ignorance about how binary data is parsed, so take this question in that light:
I'm looking to mine .max files for their internal data (such as textures, poly counts etc) so I can set up a file browser that gives a detailed description of the contents.
Has anyone done this before? My knowledge of file reads has been limited to ascii data in the past, so i'm trying to work out if I need to use some sort of struct read or unpack to bring in the max file information to search and pull out the correct values. That's pretty much where my brick wall starts!
This is a purely external python project. I want to be able to mine max files without accessing the max runtime at all.
I personally doubt this will be possible as .max files are proprietary entities handled by 3ds Max's routines. It might be possible through SDK, but still, if it was this case, the format would eventually become open-source by the community and therefore would break Autodesk's many intentional limitations.
You could, possible, then open the .max file in Maya or XSI or what not, which'd be awesome, but also allow you to open .max files saved in Max 2009 in Max 8 for example, which is intentionally being prohibited by Autodesk.
But this is purely my own speculation, might be possible, but who knows :)
Wasn't there a 3d viewer which registered a com object or plugin and with that enabled the viewer to view max files? From what I understand from the max binairy files is that alot of data is stored in data blocks, which can be any type of data a plugin wants. So with that it's hard too convert too ascii since a lot of data is binairy... but that's just what I've understand from reading some comments somewhere... I think if autodesk could easy make it ascii they would have done it long time already.. everyone wants this badly...
-Johan
relief7
05-14-2008, 04:46 PM
You might want to have a look at MaxFileReader (http://usa.autodesk.com/adsk/servlet/item?siteID=123112&id=7481504). It is a standalone tool to get information from max files. It is not written in Python though (C++).
loocas
05-14-2008, 06:04 PM
Wasn't there a 3d viewer which registered a com object or plugin and with that enabled the viewer to view max files? From what I understand from the max binairy files is that alot of data is stored in data blocks, which can be any type of data a plugin wants. So with that it's hard too convert too ascii since a lot of data is binairy... but that's just what I've understand from reading some comments somewhere... I think if autodesk could easy make it ascii they would have done it long time already.. everyone wants this badly...
-Johan
I doubt they'll ever do this as that'd allow for opening the scenes in older versions of Max, which is what Autodesk doesn't want no matter what they say ;) Also, that'd open the format for 3rd parties.
Don't know, but I think it's never gonna happen.
specxor
05-15-2008, 01:10 AM
I don't think it would be impossible, it would just require allot of reverse engineering. I recall the C++ example but I have been unable to get it to read a file with out issue. If it could be done through SDK I guess you could get a command line tool going that spits out XML or something. It would awesome to be able to do this though. I will have a look through the SDK docs to see if anything pops up.
Cheers
Dave
erilaz
05-15-2008, 01:22 AM
You might want to have a look at MaxFileReader (http://usa.autodesk.com/adsk/servlet/item?siteID=123112&id=7481504). It is a standalone tool to get information from max files. It is not written in Python though (C++).
Thanks Marcus, that looks promising. I may be able to integrate parts of it.
It's interesting that if you open a .max file in notepad you can actually extract key information such as textures used, shaders and so forth. Each character is separated with a null, but it may be possible to glean information via an ascii read by doing some clever searching or regular expressions.
I do tend to agree with loocas. For ages it wasn't in Autodesk's best interests to have an ascii/XML format, but the way things are leaning now, it would be crazy for them not to.
Imagine how much more of a joy delta versioning and file manipulation would be! :D
TheIvIaxx
05-15-2008, 02:45 AM
Can you elaborate on using python for photoshop? Sounds really useful!
Just like in max, we use it via COM. As mentioned in Kermit's link, its the same as VBS. We use it for a variety of things like launching scripts, saving stuff to the DB, etc. Its really good for having a floating non-modal window for photoshopping :)
relief7
05-15-2008, 04:39 PM
It's interesting that if you open a .max file in notepad you can actually extract key information such as textures used, shaders and so forth. Each character is separated with a null, but it may be possible to glean information via an ascii read by doing some clever searching or regular expressions.
The reason for strings having those "nulls" may come from MAX using a wide character format like Unicode or another multibyte format to save out image paths. This is necessary to support paths that contain characters which are not in the original ASCII character set.
So actually you would not have to make a search for ASCII strings but for those unicode strings. I havent been into Python very deep as of now but as far as I know it supports unicode strings. Having said that, I do not think it might be a good idea to make a brute force search on the binary file on those strings since you dont know what purpose those strings have. Generating a "bridge" via the sdk might be the safer method.
erilaz
05-28-2008, 03:58 AM
Hi, Guys,
Fist off, Camera Server that I mentioned is a simple little app im working on, that will keep animated cameras in sync. So an animator can be animating the camera and lets say a lighter is lighting the scene then his camera will have a live link to the animators etc... If that makes sense?? I am hoping to finish it 'this' week and ill post all the source for everyone to check out hopefully there will no be to much spaghetti code in there :)
David, did you ever post this example? I'm looking at some networked functionality and thought your app might be a useful resource.
specxor
05-28-2008, 11:30 PM
Hi erilaz,
Yeah I did and it worked really well. I will post the code shortly, all of the networking was handled by pyro.
Cheers
Dave
erilaz
05-29-2008, 01:19 AM
Hi erilaz,
Yeah I did and it worked really well. I will post the code shortly, all of the networking was handled by pyro.
Cheers
Dave
Thanks, that will be helpful. Incidently, are you the same Dave that went to Mad Academy? I assume it's not coincidence. :D
specxor
05-29-2008, 04:36 AM
Yep thats me!
erilaz
06-01-2008, 03:48 PM
Hi erilaz,
Yeah I did and it worked really well. I will post the code shortly, all of the networking was handled by pyro.
Cheers
Dave
*cough*
:D
specxor
06-02-2008, 01:46 AM
Ok just wipped up some small examples of using pyro for networking.
First up the server:
"""
Simple Pyro Example.
Here is the 'Server' code.
Written By David Mackenzie
dave@daveandgoliath.com
"""
import Pyro.core
import socket
class some_server(Pyro.core.ObjBase):
"""Pyro Server, handles the network transmission"""
def __init__(self):
Pyro.core.ObjBase.__init__(self)
self.ServerName = "CgTalk Example Server"
def Ping(self):
"""Ping"""
return "%s Checking In" % (socket.gethostname())
def DoSomeStuff(self, the_int):
return the_int*5
if __name__ == "__main__":
daemon = Pyro.core.Daemon(port=7756)
Pyro.core.initServer()
uri = daemon.connect(some_server(), "cgTalk")
daemon.requestLoop()
Now for a simple client to connect to the server:
"""
Here is the client code that demonstates connecting to the server and calling a remote method.
"""
def connectToServ():
cgConn = Pyro.core.getProxyForURI("PYROLOC://%s:%s/%s" % ("127.0.0.1", 7756 , "cgTalk"))
cgConn._setNewConnectionValidator
return cgConn
if __name__ == "__main__":
conn = connectToServ()
print conn.Ping()
print conn.DoSomeStuff(10)
And here is a simple com class that connects to the server:
"""
Here is a com example that we could call from max or anywhere that has com access. Please Note I have not tested the following code.
"""
import win32com.server.register
import Pyro.core
def connectToServ():
cgConn = Pyro.core.getProxyForURI("PYROLOC://%s:%s/%s" % ("127.0.0.1", 7756 , "cgTalk"))
cgConn._setNewConnectionValidator
return cgConn
class cgTalk_Com:
_public_methods_ = ['Ping', 'DoSomeStuff']
_reg_progid_ = "cgTalk.PyroExample"
_reg_clsid_ = '{59EA2ED9-8DAA-4092-8BD4-3A6069D3074B}'
def __init__(self):
self.Connection = connectToServ()
def Ping(self):
return self.Connection.Ping()
def DoSomeStuff(self, some_int):
return self.Connection.DoSomeStuff(10)
if __name__ == "__main__":
win32com.server.register.UseCommandLine(cgTalk.Com)
Hope that helps, sorry for not getting this up earlier I have been swamped lately... I have tested the server and simple example. I have not tested the com class, if you have any problems just post them up.
Cheers
Dave
erilaz
06-02-2008, 02:33 AM
Ok just wipped up some small examples of using pyro for networking.
Hope that helps, sorry for not getting this up earlier I have been swamped lately... I have tested the server and simple example. I have not tested the com class, if you have any problems just post them up.
Cheers
Dave
Thanks Dave, really appreciated. This should be wikied! :)
specxor
06-02-2008, 03:18 AM
Thanks Dave, really appreciated. This should be wikied! :)
Agreed, I have to get off my @ss and get this stuff written up
Cheers
Dave
erilaz
06-02-2008, 04:11 AM
Agreed, I have to get off my @ss and get this stuff written up
Cheers
Dave
Nah, I get the busy thing. Look how tardy I am at getting maxscript challenges written up!:D
Oh, and for those that care, I just made an obscure python joke in this thread:
http://forums.cgsociety.org/showthread.php?p=5185190#post5185190
Hot damn I love xkcd.com
Kramsurfer
06-12-2008, 11:23 AM
Just found this great converter: XML to Python Object class. Thought I'd share as many of us use xml. I spent hours learning the parsed XML syntax and trying to get the data out... then this happened... I love this python stuff...
xmlobject.py
http://www.freenet.org.nz/python/xmlobject/
Gravey
06-12-2008, 12:32 PM
Just found this great converter: XML to Python Object class. Thought I'd share as many of us use xml. I spent hours learning the parsed XML syntax and trying to get the data out... then this happened... I love this python stuff...
xmlobject.py
http://www.freenet.org.nz/python/xmlobject/Thanks heaps. This will definatly come in handy
TheIvIaxx
06-12-2008, 06:37 PM
there's also elementtree (http://effbot.org/zone/element-index.htm). Anyone have experience with both?
cgBartosz
06-12-2008, 10:40 PM
there's also elementtree (http://effbot.org/zone/element-index.htm). Anyone have experience with both?
cElementTree is the same as elementtree but written in C so it's fast.
It is about 10 times faster then XMLObject. See attachement.
XMLObject is a wrapper of standard python dom.minidom library.
Lxml or cElementTree libraries are both fast and easy to use.
specxor
06-16-2008, 06:52 AM
Hi Guys,
XMLObject is very cool, I love SQLObject to.. While we are talking about XML here is XMLClass(s) that I use all the time, I have also recreated it in MXS wrapping the dotnet objects the max and python version are virtually identical.
Cheers
Dave
erilaz
06-23-2008, 01:10 AM
Hi Guys,
XMLObject is very cool, I love SQLObject to.. While we are talking about XML here is XMLClass(s) that I use all the time, I have also recreated it in MXS wrapping the dotnet objects the max and python version a virtually identical.
Cheers
Dave
Great stuff Dave. I hope I can get some time to pull it apart to see how it all works. :)
ChemiKhazi
07-08-2008, 03:28 AM
Does anyone have a library that makes writing maxscripts pythonic? I'm thinking of starting opensourced work on making a python library for writing maxscripts instead of simply passing raw maxscript commands over COM. I might just be extending CgKit (http://cgkit.sourceforge.net/introduction.html) since it has functionalities for working with 3d objects.
TheIvIaxx
07-08-2008, 03:47 AM
Hi Guys,
XMLObject is very cool, I love SQLObject to.. While we are talking about XML here is XMLClass(s) that I use all the time, I have also recreated it in MXS wrapping the dotnet objects the max and python version are virtually identical.
Cheers
Dave
I assume this is max 9+ :cry:
As for SQLObject, i have my reservations about it and SQLALchemy. What benefits does it provide over using SQL?
Kramsurfer
07-08-2008, 05:38 PM
CgKit is pretty cool. I'm thinking one could use maxscript and the getpropnames command to generate most of the classes required to hold a MAX scene in python code. Minus lofts of course... ha ha...
specxor
07-09-2008, 07:47 AM
I assume this is max 9+ :cry:
As for SQLObject, i have my reservations about it and SQLALchemy. What benefits does it provide over using SQL?
Yep max 9+ only...
Yeah SQLObject is very cool it makes working with databases much more pythonic with all of your tables mapped to objects etc... I have looked at SQLAlchemy very quickly but have not used it, so I am not sure what benifits of SQLAlchemy are..
Cheers
Dave
sl4ppy
09-15-2008, 03:32 AM
We're developing a system which:
Keeps track of every job and what its status is.
Each deliverable's version/revision number.
Is tied into our time card software to keep track of bids and available time.
Sorry for pseudo necro-ing this thread..
I'm curious why you guys chose to use a giant Python application to handle all those tasks versus using some of the existing features in many of the more common issue-tracking applications out there (like Jira).
I had originally though about going the route you are describing (albeit via C#), but in the end decided it was redundant as we already have a perfectly viable task/status/time-card solution that integrates fairly cleanly with Perforce (our source control for everything) to link in versioning...
Kramsurfer
09-15-2008, 06:35 PM
Thought I post a Backburner hack and some telnet info for those still struggling to network render with backburner.... ( Like us... Uhhggg... )
I've written a Python command line utility to set Dependencies in BackBurner after submission. To use it, the network folder on the manager needs to have a full control share open to the artists box. Python connects to the manager via Telnet. Archives the job and then makes specific changes to the xml document on the server. Upon unarchiving the job, backburner reads the changed xml data and applies the changes.
I couldn't find a way to send the "Update Job" to BB via telnet, it appears to be binary, while every other command is xml... ?
Syntax for usage.
BBSetDependency <Ip Address> <Port> <Dependent Job Name> <Depends on Job Name> {<Depends on Job Name> ...}
Also including in the zip is a txt document outlining some of the other telnet commands I found while sniffing the connection between BB and the monitor.
Much thanks to David Mackenzie < specxor > for PyBurner, my starting point for this!
Gravey
09-16-2008, 01:56 AM
finally! thanks heaps for this awesom share. The inablity to set backburner dependencies via mxs has been holding us back for too long! I'll be checking this out asap.
lechoo
09-17-2008, 11:16 AM
What I really miss in pyburner is func for submitting new job to backburner. I tried do do that on my own.
I've intercepted data sent to backburner while submitting job. This seems to be simple xml. When I send this data using telnet connection nothing happens. By nothing I mean job doesn't appear in queue.
tn = telnetlib.Telnet("bbmanager", 3234)
print tn.read_until("backburner>", WAIT_TIME)
tn.write("new job 4692")
f = open("S:/sent.txt","rt")
try:
for line in f:
print line
tn.write(line)
finally:
f.close()
print tn.read_until("backburner>", WAIT_TIME)
sent.txt contains data from intercepted packets. I think this is right way to do it but I'm probably missing something. Do you have any ideas how to solve this problem?
vScourge
09-17-2008, 01:02 PM
I don't know what protocol Backburner uses for sure, but I doubt it's Telnet.
If the packets you're snagging always contain XML, it's more likely xmlrpc or a custom protocol. Have a look at the xmlrpclib module in the Python standard library.
Kramsurfer
09-18-2008, 07:47 PM
Lechoo: Have you tried sending the whole XML vs. sending line by line... I don't think telnet likes that...
----------------------------------------------
HELP! Having an issue with the blurPython.dlx?
I just DL'd the BlurBeta, installed for max9 , copied the dlx in and it's not working as the original.
Has the class name been changed?
Could it be because I'm in 32bit max 9 but on XP64?
Thanks
lechoo
09-22-2008, 12:28 PM
Lechoo: Have you tried sending the whole XML vs. sending line by line... I don't think telnet likes that...
I've tried both. None of them works.
Kermit27
09-24-2008, 12:53 PM
Hi,
we have two solution for communication with backburner
with telnet, u can try in command line for know command
with simple tcpip protocol, like a simple client
i use it for create a new monitor, with pyqt
an other solution is to warp 3dsmax lib from sdk for "net communication", i think more simple, but i don"t try it
Kermit
edit : i forget, i use ethereal for snif communication between manager and standart monitor
Kramsurfer
09-24-2008, 06:35 PM
Lechoo;
I've tried a few different things to create a job, but didn't see that much use as you can create any job BB will render through cmdjob.exe or 3dsmaxcmd.exe...
lechoo
09-24-2008, 06:57 PM
Lechoo;
I've tried a few different things to create a job, but didn't see that much use as you can create any job BB will render through cmdjob.exe or 3dsmaxcmd.exe...
I need to submit non-3dsmax job from non-windows machine and in this case cmdjob.exe or 3dsmaxcmd.exe can't be used.
Well, I’ve got a start going in learning some python by using a slight modification of the Lazy Evaluation Directory Treeview (http://wiki.wxpython.org/TreeControls#head-21017a515ed8a07d3b528f4ef75be5d4bda1fdaa) sample found on the wxPyWiki (http://wiki.wxpython.org/FrontPage). combined with the ThumbnailCtrl (http://xoomer.alice.it/infinity77/main/freeware.html#thumbnailctrl)from Andrea Gavana (http://xoomer.alice.it/infinity77/index.html). And its blazing fast compared to what i've seen in maxscript and dotnet so far in terms of thumbnail generation from even very large images and directory structures.!
thought that this might be of interest since I know there's a couple other guys on here in the 'asset/prop' experimenting mode currently. nothing quite finished enough for release though yet..
CyHiSo
10-07-2008, 12:23 PM
Did you register the maxes COM server while logged in with Admin rights? I have found that if you register the com server without admin rights you will (may) get an error.
Cheers
Dave
Hi!
if u mean pressing "Register" button in COM/DCOM Server Control Utility - I did so.But i get:
File "C:\Python25\Lib\site-packages\pythonwin\pywin\framework\scriptutils.py", line 309, in RunScript
debugger.run(codeObject, __main__.__dict__, start_stepping=0)
File "C:\Python25\Lib\site-packages\pythonwin\pywin\debugger\__init__.py", line 60, in run
_GetCurrentDebugger().run(cmd, globals,locals, start_stepping)
File "C:\Python25\Lib\site-packages\pythonwin\pywin\debugger\debugger.py", line 624, in run
exec cmd in globals, locals
File "C:\Python25\Script1.py", line 2, in <module>
conn = win32com.client.Dispatch("MAX.Application.8")
File "C:\Python25\Lib\site-packages\win32com\client\__init__.py", line 95, in Dispatch
dispatch, userName = dynamic._GetGoodDispatchAndUserName(dispatch,userName,clsctx)
File "C:\Python25\Lib\site-packages\win32com\client\dynamic.py", line 98, in _GetGoodDispatchAndUserName
return (_GetGoodDispatch(IDispatch, clsctx), userName)
File "C:\Python25\Lib\site-packages\win32com\client\dynamic.py", line 78, in _GetGoodDispatch
IDispatch = pythoncom.CoCreateInstance(IDispatch, None, clsctx, pythoncom.IID_IDispatch)
com_error: (-2147221005, 'Invalid class string', None, None)
again and again..what am i supposed to do?
vScourge
10-07-2008, 09:14 PM
IDispatch = pythoncom.CoCreateInstance(IDispatch, None, clsctx, pythoncom.IID_IDispatch)
com_error: (-2147221005, 'Invalid class string', None, None)
Yeah, you need to register Max with COM, that error means Windows doesn't know about it.
Try this. Start Max then run the attached MaxScript. It should add the necessary info to registry. Then try to do your Dispatch again and see what happens.
CyHiSo
10-08-2008, 09:05 AM
Yeah, you need to register Max with COM, that error means Windows doesn't know about it.
Try this. Start Max then run the attached MaxScript. It should add the necessary info to registry. Then try to do your Dispatch again and see what happens.
Thank u very much!:) everything it's ok right now:)
vScourge
10-16-2008, 02:00 AM
Thank u very much!:) everything it's ok right now:)
Sure thing. I also added the code from that script to registerPythonCom.ms in my sample files (http://www.volition-inc.com/gdc/GDC2008_AdamPletcher_PythonSamples.zip) from my GDC talk (http://www.volition-inc.com/gdc/).
If anyone was having problems getting my COM samples to work before, grab the updated ZIP and give it a go.
Kramsurfer
11-13-2008, 08:33 PM
I've added some functions to my BackBurner Class and made it directly available in 3dsmax via a COM connection.. Though I'd post the latest since there's a few posts about BB control on the forum currently...
Just unzip in
<max>\\plugins\\Scripted Global Functions\\
There will be a command window flash when Max starts and then in maxScript there should be a global structure PythonLib with a backburner property.
PythonLib.BackBurner.GetJobList <manager name> <manager port>
Should list ALL the jobs on that manager.
More functions coming soon !
Edit1: Sorry About that typo... New zip...
PiXeL_MoNKeY
11-13-2008, 10:09 PM
Kramsurfer it is giving me errors in 2009 (x64 and x86):-- Error occurred in anonymous codeblock; filename: C:\Program Files\Autodesk\3ds Max 2009\PlugIns\Script Global Functions\PythonLib_BackBurner.ms; position: 237
-- Frame:
-- pythonModualsStruct: StructDef:pythonModualsStruct
-- Error occurred during fileIn in <File:C:\Program Files\Autodesk\3ds Max 2009\PlugIns\Script Global Functions\PythonLib_BackBurner.ms>
>> MAXScript Auto-load Script Error - C:\Program Files\Autodesk\3ds Max 2009\PlugIns\Script Global Functions\PythonLib_BackBurner.ms Exception: -- Runtime error: createOLEObject: can't find server PythonLib.BackBurner <<-Eric
Edit: the path according to the script is plugins\\Global Scripted Functions\\, not \\Plugins\\Script Global Functions\\ as documented. You may want to update that. Still errors do to the spaces in the paths, I believe.
EDIT2: I modified the script to get rid of the error change the doscommand line to:dosCommand ( "\""+( getDir #maxRoot ) +"plugins\\Script Global Functions\\PythonLib_BackBurner.py\"")
PiXeL_MoNKeY
11-13-2008, 10:36 PM
Here is a modified PythonLib_Backburner.ms, that won't flash the dos window:(
struct pythonModualsStruct ( BackBurner )
hiddendosCommand ( "\""+( getDir #maxRoot ) +"plugins/Script Global Functions/PythonLib_BackBurner.py\"") startpath:"c:/"
global PythonLib = ( pythonModualsStruct BackBurner:(createOLEObject("PythonLib.BackBurner")) )
)
-Eric
PiXeL_MoNKeY
11-13-2008, 10:51 PM
For some reason all .GetJobList returns is "Sorting JobList". No jobs are returned, eventhough I have 5 in the queue.
-Eric
Kramsurfer
11-13-2008, 11:25 PM
Always an issue when you try to quickly tear a piece of something out of a bigger construct!
Updated PythonLib.BackBurner
PiXeL_MoNKeY
11-14-2008, 03:51 PM
Thanks for the update, but the joblist output really isn't helpful:0FEF27CE Complete Autodesk 3ds Max 2009 (32-bitOn top of that it is returning a multi-line string, rather than something useful.
-Eric
Kramsurfer
11-17-2008, 05:08 PM
It returns a job handle, very useful for controlling a job or getting further information about that job. Current rendering status of that job, The name of the job and what type of job it is. That's all BB returns for a joblist and it in plain English in one string and tab delimited for easy use in MXscript.
Sorry it wasn't useful to you.
PiXeL_MoNKeY
11-17-2008, 05:47 PM
As you can see from what I posted it is turnacating the info, so I get the handle, status, and part of the version.
-Eric
Kramsurfer
11-17-2008, 07:33 PM
Okay, uploaded an update to the updated version, it's now 4.0... I'm not using 2009, but will be soon... so thanks for the Beta Testing and a bug find in my code...
PiXeL_MoNKeY
11-17-2008, 08:35 PM
As I mentioned before, you could always put the DosCommand in a try/catch with HiddenDosCommand as I outlined previously for those using 2008+ or AVG so they don't get the cmd prompt flash, or just replace the doscommand code with the hiddendoscommand in this copy of the code:(
struct pythonModualsStruct ( BackBurner )
try (hiddendosCommand ( "\""+( getDir #maxRoot ) +"plugins\\Script Global Functions\\PythonLib_BackBurner.py\"") startpath:"c:/") catch (dosCommand ( "\""+( getDir #maxRoot ) +"plugins\\Scripted Global Functions\\PythonLib_BackBurner.py\""))
global PythonLib = ( pythonModualsStruct BackBurner:(createOLEObject("PythonLib.BackBurner")) )
)-Eric
Kramsurfer
11-17-2008, 09:45 PM
Done. Thanks Eric. Can't wait to make the move to 2009, so much good stuff there...
ndufort
12-08-2008, 07:06 PM
As you can see there is a ultra simple function that will just execute whatever is parsed to it. Now for the Python part, this will require the win32 module.
#Import win32com.
import win32com.client
#Create a connection to Max
conn = win32com.client.Dispatch("MAX.Application.9")
I am having trouble Dispatch'ing MAX. I have the trial version of 2009, and I always get an "Invalid class string" error (I tried to change 9 by 11 or 2009, and also without a version number). I understand this has something to do with Max 2009 not being registered, correct?
I searched a bit the pywin32 mailing list archives, but even by looking at the COM Makepy Utility, I could not find anything that would help. I also read about creating a Reg entry through pythoncom.CreateGuid(), but that did not help either (I tried to mimic what was there for Photoshop since I can do win32com.client.Dispatch("Photoshop.Application") without a problem).
Could anyone tell me what I need to look for to get this working?
Thanks. nico.
TheIvIaxx
12-08-2008, 11:05 PM
I am having trouble Dispatch'ing MAX. I have the trial version of 2009, and I always get an "Invalid class string" error (I tried to change 9 by 11 or 2009, and also without a version number). I understand this has something to do with Max 2009 not being registered, correct?
I searched a bit the pywin32 mailing list archives, but even by looking at the COM Makepy Utility, I could not find anything that would help. I also read about creating a Reg entry through pythoncom.CreateGuid(), but that did not help either (I tried to mimic what was there for Photoshop since I can do win32com.client.Dispatch("Photoshop.Application") without a problem).
Could anyone tell me what I need to look for to get this working?
Thanks. nico.
I think the names you can use are listed in the registry in HKEY_CLASSES_ROOT. For max 8, there is a key called MAX.Application.8, see if there is a similar one for 2009.
vScourge
12-08-2008, 11:15 PM
I am having trouble Dispatch'ing MAX. I have the trial version of 2009, and I always get an "Invalid class string" error (I tried to change 9 by 11 or 2009, and also without a version number). I understand this has something to do with Max 2009 not being registered, correct?
See my reply above (http://forums.cgsociety.org/showthread.php?p=5436099#post5436099), dated 10-15-2008, 08:00 PM. Specifically the maxscript file I mentioned. It should help you make Max register itself as a COM server.
ndufort
12-09-2008, 12:58 PM
See my reply above (http://forums.cgsociety.org/showthread.php?p=5436099#post5436099), dated 10-15-2008, 08:00 PM. Specifically the maxscript file I mentioned. It should help you make Max register itself as a COM server.
Thanks for the script; this is getting me moving forward. Please forgive my ignorance on all this, but after installing the avguard plugin, and running your script, I get an error that reg_key/HKey is 'undefined'. Might this because of a lack of permissions to access the registry properly? Where does the value of HKey come from when running the script?
Thanks again for your help. Appreciated.
nico
vScourge
12-09-2008, 10:30 PM
Can you paste in the exact error you're seeing? And what maxscript line is triggering it?
ndufort
12-10-2008, 03:16 PM
Can you paste in the exact error you're seeing? And what maxscript line is triggering it?
Note: this was tested on version 8--not 2009, at work (hence my concern about permissions to write to the registry). From running register3dsMaxCom.ms:
-- Error occured in create_reg_key(); filename C:\[path to file]\register3dsMaxCom.ms;
position: 470
-- Frame:
-- HKey: HKEY_CLASSES_ROOT
-- key_value_name: ""
-- key_value: "OLE Automation MAX Application"
-- reg_key: undefined
-- key_name: "Max.Application"
-- key_value_type: #REG_SZ
-- called in anonymous codeblock
-- Frame:
-- write_sub_key_data: write_sub_key_data()
-- create_reg_key: create_reg_key()
-- max_version: "8"
-- reg_key: undefined
-- Type error: HKey requires HKey, got: undefined
OK
The line highlighted in the script is:
registry.setValue reg_key key_value_name key_value_type key_value
I am trying to ask someone with Admin privileges to run the script to see if he gets the same error.
Thank you for your time,
nico
ndufort
12-10-2008, 09:48 PM
Note: this was tested on version 8--not 2009, at work (hence my concern about permissions to write to the registry). From running register3dsMaxCom.ms:
-- Error occured in create_reg_key(); filename C:\[path to file]\register3dsMaxCom.ms;
position: 470
-- Frame:
-- HKey: HKEY_CLASSES_ROOT
-- key_value_name: ""
-- key_value: "OLE Automation MAX Application"
-- reg_key: undefined
-- key_name: "Max.Application"
-- key_value_type: #REG_SZ
-- called in anonymous codeblock
-- Frame:
-- write_sub_key_data: write_sub_key_data()
-- create_reg_key: create_reg_key()
-- max_version: "8"
-- reg_key: undefined
-- Type error: HKey requires HKey, got: undefined
OK
The line highlighted in the script is:
registry.setValue reg_key key_value_name key_value_type key_value
I am trying to ask someone with Admin privileges to run the script to see if he gets the same error.
Thank you for your time,
nico
This must be something with Admin privileges: I just tried this at home with 2009, and I managed to run the previous examples fine. I will check with our SysAdmin at work tomorrow to get around this. Man, do I miss working on Linux... :sad:
Thanks everyone for the help, and thanks Adam for your blog as I would have never known how to get started with Python to write my Photoshop tools, and now--let's hope--to write some procedures for Max.
Cheers. nico
ndufort
12-18-2008, 12:54 PM
Well, we're at it again. While I had no problem getting it to work at home, I finally got a SysAdmin at work to run the scripts and we got some errors. He ran the Maxscript fine (to register Max), but when trying to run the Python code, it complained about a class not being registered.
Python code:
#Import win32com.
import win32com.client
#Create a connection to Max
conn = win32com.client.Dispatch("MAX.Application.8")
Error:
Traceback (most recent call last):
File "path\to\callingmaxsc.py", line 6, in ?
con = win32com.client.Dispatch("MAX.Application.8")
File "C:\Python24\lib\site-packages\win32com\client\dynamic.py", line 95, in Dispatch
dispatch, username = dynamic._GetGoodDispatchAndUserName(dispatch, username, clsctx)
File "C:\Python24\lib\site-packages\win32com\client\dynamic.py", line 98, in _GetGoodDispatchAndUserName
return (_GetGoodDispatchAndUserName(IDispatch, clsctx), userName)
File "C:\Python24\lib\site-packages\win32com\client\dynamic.py", line 78, in _GetGoodDispatch
IDispatch = pythoncom.CoCreateInstance(IDispatch, None, clsctx, pythoncom.IID_IDispatch)
com_error: (-2147221164, 'Class not registered', None, None)
This was run by the Admin. We looked at the registry, and all the keys and values looked good. Setup: Max 8, Python 2.4.3 with pywin32, XP 64 SP2.
I got it to work at home with XP SP3, Python 2.5 and pywin32, Max 2009. I will try, when I get home, to use an older version of Python and Max, to see if I can reproduce the problem. I also tried using comtypes since I had some issues with win32com, but I get the same errors, so it has something to do with the classes in the register not being found...
Anyone who encountered this problem? I will try to post again before the weekend to see if I can reproduce this at home with older versions of Max and Python.
Thanks.
Nico
ndufort
12-18-2008, 05:42 PM
Update on this: I was maybe expecting too much. When I called win32com.client.Dispatch("MAX.Application.8"), I was expecting the script to launch Max, the way it would launch Photoshop. After I had Max open, everything worked fine.
I'm not a programmer, but I would love it if someone could explain to me the difference when I do:
win32com.client.Dispatch("MAX.Application")
and
win32com.client.Dispatch("Photoshop.Application")
Why can the script launch Photoshop but not Max? It is not a problem at all as I will need Max to be running in the first place, but I am curious as to why the two apps behave differently.
Cheers. nico
vScourge
12-19-2008, 07:13 PM
In my experience they don't behave differently. Both of those commands open their respective app on my machines. I couldn't tell you why, perhaps you're missing some registry key/value that's normally there?
Also, if there's an open instance of Max (or Photoshop, for that matter) when you do the dispatch, it will use that one and not open a new instance. Is it possible you had an instance of 3dsmax.exe running in the background? That sometimes happens after it crashes, etc. If so, it would consume any COM connections you make.
Just a thought.
ndu, I was having the same Hkey error here (Both with max2008 32bit, and max2009 32bit, though the script appears to work in the 64bit installs?
Anyway, this is the contents of the regfile if you were to install in 2008, modify the location of LocalServer32 to reflect your max installation though, also adjust the MAX.Application.10's to read MAX.Application.11's if you're doing it for 2009.
this is basically the final output of the above script, with the localserver being added in so that it will launch that app if the required dispatch isn't already open on the machine
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\MAX.Application]
@="OLE Automation MAX Application"
[HKEY_CLASSES_ROOT\MAX.Application\Clsid]
@="{7FA22CB1-D26F-11d0-B260-00A0240CEEA3}"
[HKEY_CLASSES_ROOT\MAX.Application\CurVer]
@="MAX.Application.10"
[HKEY_CLASSES_ROOT\MAX.Application.10]
@="OLE Automation MAX 10.0 Application"
[HKEY_CLASSES_ROOT\MAX.Application.10\Clsid]
@="{7FA22CB1-D26F-11d0-B260-00A0240CEEA3}"
[HKEY_CLASSES_ROOT\CLSID\{7FA22CB1-D26F-11d0-B260-00A0240CEEA3}]
@="OLE Automation MAX 10.0 Application"
[HKEY_CLASSES_ROOT\CLSID\{7FA22CB1-D26F-11d0-B260-00A0240CEEA3}\Localserver32]
@="C:\\3dsmax08\\3dsmax.exe"
[HKEY_CLASSES_ROOT\CLSID\{7FA22CB1-D26F-11d0-B260-00A0240CEEA3}\ProgID]
@="MAX.Application.10"
[HKEY_CLASSES_ROOT\CLSID\{7FA22CB1-D26F-11d0-B260-00A0240CEEA3}\VersionIndependentProgID]
@="MAX.Application"
would be nice to figure out why the script is failing though, as doing it manually doesn't allow for easy access to different versions of the application on the same workstation without running a different .reg file
JamSession
01-14-2009, 01:37 AM
Has anyone been able to query Max scene elements through python?
Basic things like get selected objects, or get the joints in the scene into a python array?
example:
myArray = []
mx.command_from_python('for i in $ do ("python.myArray.append(i)")')
#so I could later do something like
for obj in myArray:
print obj
vScourge
01-14-2009, 03:18 AM
If you're using COM to connect to Max using Python, you're going to be limited to the data types that COM supports for return values. Offhand, I believe the supported types coming from Max are string, float, integer, boolean, color and one-dimensional arrays of those same types.
In any case, if you issue a command from Python that would normally return an data type that's specific to 3ds Max (such as Color, Node, quat, etc), the COM layer will throw an error.
I've dealt with this in my Python-Max tools by creating a function that acts like a little layer between Python and MaxScript. If the command executed returns a value that's not one of the native COM types, it casts the value to a string before sending it back to Python. That way the Python code has the option of doing something useful with it instead of being faced with a useless error. The wrapper function is then what's exposed over COM, or some other function that uses it.
For instance, a node value in MaxScript would normally look like this:
$Teapot:Teapot01 @ [-36.208855,-22.871155,0.000000]
A Python script using a type-casting wrapper would know that wasn't a supported COM type, and convert it to a string. The Python script would instead get this back:
"$Teapot:Teapot01 @ [-36.208855,-22.871155,0.000000]"
You can't interact with that in Python the same way you would in MaxScript, but you do have some info to work with (object's type, name, position). You just need to parse it from the string.
Attached is a small MaxScript I wrote for my GDC talk last year. There's one function for converting Max-specific data types to something COM can grok, and another that takes requests from Python and actually executes the commands, calling the convert function as needed. The second function is also registered as a COM object for your Python tools to use.
ndufort
01-14-2009, 10:37 AM
Has anyone been able to query Max scene elements through python?
Basic things like get selected objects, or get the joints in the scene into a python array?
example:
myArray = []
mx.command_from_python('for i in $ do ("python.myArray.append(i)")')
#so I could later do something like
for obj in myArray:
print obj
I really don't know much about MaxScript, but for my tool, where I need to make a list of cameras to extract values from, I had to create the array inside Max and then call it from Python.
(the MaxDo is just a shorter name from the earlier example using DoSomething)
conn.MaxDo('myMaxArray = #()') # create array in Max
conn.MaxDo('myMaxArray[1]') # access the first element in your Python code
JamSession
01-14-2009, 10:19 PM
I really don't know much about MaxScript, but for my tool, where I need to make a list of cameras to extract values from, I had to create the array inside Max and then call it from Python.
(the MaxDo is just a shorter name from the earlier example using DoSomething)
conn.MaxDo('myMaxArray = #()') # create array in Max
conn.MaxDo('myMaxArray[1]') # access the first element in your Python code
Thanks for the ideas
90% of the time I am dealing with arrays, I need the size and looping abilities. So calling a max array doesn't seem too valuable since I can't
for i in myArray:
print i
But I do like the idea of getting a string from Max and parsing the crap out of that. Especially since python is pretty good dealing with strings. :)
Kramsurfer
01-15-2009, 12:58 AM
checkout the "SafeArrayWrapper" class in MaxScript. I've passed arrays that way..
ndufort
01-15-2009, 01:03 PM
Thanks for the ideas
90% of the time I am dealing with arrays, I need the size and looping abilities. So calling a max array doesn't seem too valuable since I can't
for i in myArray:
print i
But I do like the idea of getting a string from Max and parsing the crap out of that. Especially since python is pretty good dealing with strings. :)
Again, I'm no wiz' at this, but I believe you can get the content of a MaxArray to Python and work with it: myPyContainer = conn.MaxDo('myMaxArray'). I say container because I "think" you will get a tuple, not an array. You should be able to then loop through it, or even change it to an array for your needs.
vScourge
01-15-2009, 03:13 PM
Yes, you'll get arrays back as tuples, as long as they contain data types supported by COM, or you put a convert-to-string function in front of it like the script I posted above.
I've also noticed Max will cause COM to throw an error if the array its sending is empty. The script I posted above gets around this by checking before returning the value, and sending a special string back to Python you can then turn into an empty list, tuple, etc.
ndufort
01-16-2009, 09:27 AM
Yes, you'll get arrays back as tuples, as long as they contain data types supported by COM, or you put a convert-to-string function in front of it like the script I posted above.
I've also noticed Max will cause COM to throw an error if the array its sending is empty. The script I posted above gets around this by checking before returning the value, and sending a special string back to Python you can then turn into an empty list, tuple, etc.
True. I need to clarify that anything I have posted is based on the scripts provided by Adam. Definitively a life safer.
While I'm at it, anyone has noticed rounding issues between Max and Python? In my example, I was converting cameras to .chan. I noticed that the precision of the decimal values where different (around the 4th or 5th number). I compared the output from the original Maxscript and my script where I tried to do the manip in Python, and I got different numbers. In the end, I just did the manip of the numbers inside Max and passed the value back to Python.
vScourge
01-16-2009, 01:07 PM
While I'm at it, anyone has noticed rounding issues between Max and Python?
You mean stuff like this?
>>> 18.49 * 100
1848.9999999999998
>>> 0.1
0.10000000000000001
Most languages (machines, actually) work this way, but some sorta hide it more than others. MaxScript, for instance, is a little less obvious about it. Here's a somewhat long explanation:
http://docs.python.org/tutorial/floatingpoint.html
JamSession
01-19-2009, 08:20 PM
Again, I'm no wiz' at this, but I believe you can get the content of a MaxArray to Python and work with it: myPyContainer = conn.MaxDo('myMaxArray'). I say container because I "think" you will get a tuple, not an array. You should be able to then loop through it, or even change it to an array for your needs.
Thanks guys! Here is a snippet to return selected objects to python, not pretty, but moving in the correct direction.
*This is using vScourge lovely Max COM
import win32com.client
mx = win32com.client.Dispatch('Max.Application')
mx._FlagAsMethod('command_from_python')
mx.command_from_python ('myArray = #()')
mx.command_from_python ('for o in selection do (append myArray o)')
nArray= (mx.command_from_python('myArray'))
for i in nArray:
print i
Unfortunately my Maxscripting is very very weak. I am a Maya/Mel scripter with some good knowledge in Python, and this new project requires maxscripting so I am trying to avoid completely learning a new language if possible!
toRigOrNotToRig
02-12-2009, 06:10 PM
Hi! I am interested in using Python in Max. I am trying to get the example in the first post to work.
I run the MaxScript, and it returns "OK". So that's okay.
Then I run the Python script, and it runs, nothing happens. No box appears in Max... but no errors either... it blinks briefly and then it just goes onto the next line ready for another entry.
I've never used Python before, am I doing something wrong?
I'm on XP, using Python 2.6.1 with the win32 module it says you need, and Max 9 with SP2.
Thanks!
ndufort
02-17-2009, 11:08 AM
Hi! I am interested in using Python in Max. I am trying to get the example in the first post to work.
I run the MaxScript, and it returns "OK". So that's okay.
Then I run the Python script, and it runs, nothing happens. No box appears in Max... but no errors either... it blinks briefly and then it just goes onto the next line ready for another entry.
I've never used Python before, am I doing something wrong?
I'm on XP, using Python 2.6.1 with the win32 module it says you need, and Max 9 with SP2.
Thanks!
Could you show us the Max and Python code you are running? That could help us see what you might be missing.
You mentioned being new to Python. There is a lot of learning material outthere, but it also can be too much to look at for a newcomer. Do you have a background in scripting or programming in a different language? Based on this, we could give you a few pointers to what resources could help you learn Python.
Cheers. nico
toRigOrNotToRig
02-17-2009, 05:50 PM
Could you show us the Max and Python code you are running? That could help us see what you might be missing.
You mentioned being new to Python. There is a lot of learning material outthere, but it also can be too much to look at for a newcomer. Do you have a background in scripting or programming in a different language? Based on this, we could give you a few pointers to what resources could help you learn Python.
Cheers. nico
It's a copy of the code from the first post with the comments removed:
The Max part, which when run, returns "OK":
fn DoSomething obj = ( try(
execute obj
return true
)catch(
return false
)
)
registerOLEInterface #(DoSomething)
The python part, which throws no errors, but fails to do anything:
import win32com.client
conn = win32com.client.Dispatch("MAX.Application.9")
conn._FlagAsMethod("DoSomething")
conn.DoSomething("Box()")
I know quite a bit of MEL and some C++. I also know a little MaxScript. I'd say I'm probably an intermediate user. I understand how code works, and can look up things if I don't know them. The weird thing about Python is the use of indenting as a way of demarcating code blocks, as opposed to using parenthesis, etc. I'm not indenting any of the lines in the Python part, and I don't know if maybe I'm missing something, or maybe I'm not running it the right way in the Idle interface? I type it in, and hit return, but it doens't do anything. I've managed to get some simple code (i.e. "hello world" type stuff) to work in Python. So, I don't know :D
B.Opatowiecki
02-19-2009, 08:24 AM
Could someone delete this... Sorry, Thank you.
vBulletin v3.0.5, Copyright ©2000-2012, Jelsoft Enterprises Ltd.