Python 3.4

#1

Tobias,

Crossbar runs on twisted that is partially ported to 3.4, what are your
plans/roadmap to update crossbar to run on 3.4 and/or switch to asyncio?

Additionally, a general question, does crossbar.io support loading
components written in 3.4 or later, how does that work, requirements?

Thanks for all of your hard work on this project, VERY cool stuff!

0 Likes

#2

Looks like I answered my own question… or is there another way to use an imported component that is written in 3.4 with asyncio?

2015-01-15 11:37:53-0500 [Container 5730] Entering event loop …
2015-01-15 11:37:53-0500 [Container 5730] Warning: process utilities not available
2015-01-15 11:37:53-0500 [Controller 5718] Container with ID ‘worker2’ and PID 5730 started
2015-01-15 11:37:53-0500 [Controller 5718] Container ‘worker2’: PYTHONPATH extended
2015-01-15 11:37:54-0500 [Container 5730] ERROR: failed to import class hello.Main.MyBackendComponent (“invalid syntax (Main.py, line 36)”)
2015-01-15 11:37:54-0500 [Controller 5718] Traceback (most recent call last):
2015-01-15 11:37:54-0500 [Controller 5718] File “/usr/local/lib/python2.7/dist-packages/crossbar/controller/node.py”, line 190, in run_node_config
2015-01-15 11:37:54-0500 [Controller 5718] yield self._run_node_config(config)
2015-01-15 11:37:54-0500 [Controller 5718] ApplicationError: ApplicationError(‘crossbar.error.cannot_import’, args = (u’ERROR: failed to import class hello.Main.MyBackendComponent (“invalid syntax (Main.py, line 36)”)’, u’Traceback (most recent call last):\n File “/usr/local/lib/python2.7/dist-packages/crossbar/worker/container.py”, line 214, in start_container_component\n module = importlib.import_module(module_name)\n File “/usr/lib/python2.7/importlib/init.py”, line 37, in import_module\n import(name)\n File “/home/dave/PycharmProjects/CrossbarDemos/HelloDemo/hello/Main.py”, line 36\n reg = yield from self.register(utcnow, ‘com.timeservice.now’)\n ^\nSyntaxError: invalid syntax\n’), kwargs = {})
2015-01-15 11:37:54-0500 [Controller 5718] Main loop terminated.

``

0 Likes

#3

And here is the backend component, pretty much straight from a demo, I am referring to (you can see the old application router code commented out):

import json
import datetime
import asyncio
from autobahn.asyncio import wamp, websocket

class DavesTestClass(object):
def init(self):
self.name = ‘Dave’
self.age = 51

class MyBackendComponent(wamp.ApplicationSession):
“”"
Application code goes here. This is an example component that provides
a simple procedure which can be called remotely from any WAMP peer.
It also publishes an event every second to some topic.
“”"
def onConnect(self):
self.join(“realm1”)

@asyncio.coroutine
def onJoin(self, details):

def jsonDefault(o): # https://freepythontips.wordpress.com/2013/08/08/storing-and-loading-data-with-json/
return o.dict

Register a procedure for remote calling

def utcnow():
now = datetime.datetime.utcnow()
time = now.strftime("%Y-%m-%dT%H:%M:%SZ") # six.u()
print(time)
return time

reg = yield from self.register(utcnow, ‘com.timeservice.now’)
print(“Registered procedure with ID {}”.format(reg.id))

Publish events to a topic

dave = DavesTestClass()

print(dave)

while True:
objToSend = json.dumps(dave, default=jsonDefault, indent=4)
self.publish(‘com.myapp.topic1’, objToSend)
print('Published: ', objToSend)
yield from asyncio.sleep(1)

if name == ‘main’:

# 1) create a WAMP router factory

router_factory = wamp.RouterFactory()

···

# 2) create a WAMP router session factory

session_factory = wamp.RouterSessionFactory(router_factory)

# 3) Optionally, add embedded WAMP application sessions to the router

session_factory.add(MyBackendComponent())

# 4) create a WAMP-over-WebSocket transport server factory

transport_factory = websocket.WampWebSocketServerFactory(session_factory, debug=False, debug_wamp=False)

# 5) start the server

loop = asyncio.get_event_loop()

coro = loop.create_server(transport_factory, ‘127.0.0.1’, 8080)

server = loop.run_until_complete(coro)

try:

# 6) now enter the asyncio event loop

loop.run_forever()

except KeyboardInterrupt:

pass

finally:

server.close()

loop.close()

``

My crossbar config, again straight from a demo with an adjusted import class:

{
“controller”: {
},
“workers”: [
{
“type”: “router”,
“options”: {
“pythonpath”: ["…"]
},
“realms”: [
{
“name”: “realm1”,
“roles”: [
{
“name”: “anonymous”,
“permissions”: [
{
“uri”: “*”,
“publish”: true,
“subscribe”: true,
“call”: true,
“register”: true
}
]
}
]
}
],
“transports”: [
{
“type”: “web”,
“endpoint”: {
“type”: “tcp”,
“port”: 8080
},
“paths”: {
“/”: {
“type”: “static”,
“directory”: “…/hello/web”
},
“ws”: {
“type”: “websocket”
}
}
}
]
},
{
“type”: “container”,
“options”: {
“pythonpath”: ["…"]
},
“components”: [
{
“type”: “class”,
“classname”: “hello.Main.MyBackendComponent”,
“realm”: “realm1”,
“transport”: {
“type”: “websocket”,
“endpoint”: {
“type”: “tcp”,
“host”: “127.0.0.1”,
“port”: 8080
},
“url”: “ws://127.0.0.1:8080/ws”
}
}
]
}
]
}

``

0 Likes

#4

Sure. You need to run the component as a guest worker.

Python/asyncio components cannot be run inside native workers (side-by-side in routers/containers)

···

Am 15.01.2015 um 17:40 schrieb Dave Thomas:

    Looks like I answered my own question.... or is there another way to
    use an imported component that is written in 3.4 with asyncio?

0 Likes

#5

Hi Dave,

Tobias,

Crossbar runs on twisted that is partially ported to 3.4, what are your
plans/roadmap to update crossbar to run on 3.4 and/or switch to asyncio?

We will support running Crossbar.io under Python 3 as soon as Twisted has "sufficient" support for Python 3 (that is, for all the stuff we use in Crossbar.io)

We have no plans, needs or reasons to port to asyncio (no gain, only pain).

Additionally, a general question, does crossbar.io
<http://crossbar.io/> support loading
components written in 3.4 or later, how does that work, requirements?

Yes. These are run exactly as Node, Java or other components: Crossbar.io can start and monitor so-called guest workers. These can be anything ..

Thanks for all of your hard work on this project, VERY cool stuff!

Great, thanks!

···

Am 15.01.2015 um 16:27 schrieb Dave Thomas:

--
You received this message because you are subscribed to the Google
Groups "Autobahn" group.
To unsubscribe from this group and stop receiving emails from it, send
an email to autobahnws+...@googlegroups.com
<mailto:autobahnws+...@googlegroups.com>.
To post to this group, send email to autob...@googlegroups.com
<mailto:autob...@googlegroups.com>.
To view this discussion on the web visit
https://groups.google.com/d/msgid/autobahnws/CAAPehXYRhfK%2BBStP%2BEOfv%2BxROXLFeDwUx2X%2BQUs7YUejV1pMnQ%40mail.gmail.com
<https://groups.google.com/d/msgid/autobahnws/CAAPehXYRhfK%2BBStP%2BEOfv%2BxROXLFeDwUx2X%2BQUs7YUejV1pMnQ%40mail.gmail.com?utm_medium=email&utm_source=footer>.
For more options, visit https://groups.google.com/d/optout.

0 Likes

#6

Tobias,

I REALLY appreciate that you take the time to monitor these posts! I wasn’t expecting a same day response! Thank you.

I ended up getting a python 3.4 file to run and will document it here for others.

Ok, so I know that this is all over the documents but it is REALLY important to remember that crossbar is truly decoupled as the router from application logic (yes, you can run a python 2.7 file from INSIDE the router process as far as I can tell as a component), but as Tobias says, it’s a current requirement to run a python 3.4 file as a guest READ: Guest process, OR completely decoupled!

So what does this mean? Pay close attention to the router config. If you are referencing components in your router config section

 "components": [
            // WAMP app components running side-by-side with this router
         ],

``

or components in your container config section

{

“type”: “container”,

“options”: {

“pythonpath”: ["…"]

},

“components”: [

{

“type”: “class”,

“classname”: “hello.hello.AppSession”,

“realm”: “realm1”,

“transport”: {

“type”: “websocket”,

“endpoint”: {

“type”: “tcp”,

“host”: “127.0.0.1”,

“port”: 8080

},

“url”: “ws://127.0.0.1:8080/ws”

}

}

]

}

``

and those components are python 3.4 files they will NOT run (take all this with a grain of salt as it is just my understanding, posting here to help others and save them time). See the first line in the docs which was a dead giveaway for me:

Python Components are worker processes spawned by Crossbar.io which directly host application classes written in Python deriving from autobahn.twisted.wamp.ApplicationSession.

Twisted as of right now is not fully ported to python 3 so it’s not going to run your python 3!

Your worker process, again as of current, is running in python 2, and will therefore NOT understand python 3 syntax, you will get a traceback when trying to start crossbar.

Adding to what I said about decoupling, or the other option that Tobias mentioned as a guest process (not sure if there is any benefit to either option, haven’t tried guest yet), think of your python 3 file running as a “client” to the router READ: “router black box appliance”. You should not have any references to your application logic file in your config to completely decouple it! When running your python 3 file it should join the realm in the router DYNAMICALLY unless you are running it as a guest: http://crossbar.io/docs/Guest-Configuration/

So how did I get this running? First, remove any components or container config if you don’t need them. Here is my config for example:

{
   "controller": {
   },
   "workers": [
      {
         "type": "router",
         "options": {
            "title": "WAMP Router"
         },
         "realms": [
            {
               "name": "realm1",
               "roles": [
                  {
                     "name": "anonymous",
                     "permissions": [
                        {
                           "uri": "*",
                           "publish": true,
                           "subscribe": true,
                           "call": true,
                           "register": true
                        }
                     ]
                  }
               ]
            }
         ],
         "transports": [
            {
               "type": "web",
               "endpoint": {
                  "type": "tcp",
                  "port": 8080
               },
               "paths": {
                  "/": {
                     "type": "static",
                     "directory": "<Name of your front end project directory if you want to debug at the same time!>"
                  },
                  "ws": {
                     "type": "websocket"
                  }
               }
            }
         ]
      }
   ]
}

``

When you run your python 3 add an application runner from autobahn (maybe there is a better way?) and it will JOIN the realm of your WAMP router, therefore you could run your python on one server and your WAMP router on a completely different server! Decoupled remember!

if __name__ == '__main__':
    runner = ApplicationRunner(url="ws://localhost:8080/ws", realm="realm1")
    runner.run(AppSession)

``

Just thought I would post for others, guess some of this might be obvious, but thought I would share!

Thanks again Tavendo for some awesome stuff!

Dave

0 Likes