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.
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.
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
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
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?
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.
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!
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.