LEW21 / pydbus

Pythonic DBus library
GNU Lesser General Public License v2.1
327 stars 76 forks source link

Flask main loop vs glib main loop of pydbus #24

Closed ghost closed 7 years ago

ghost commented 7 years ago

Hi, I am thinking of using your pydbus to establish a rpc connection to a c++ program. At the same time I am using a Flask program whose main loop may interfere with the glib main loop. How can I make this work, or am I wrong here? Hope someone can help me, if this is even the right place to ask for that... (if not, i am sry)

Greetings eX

LEW21 commented 7 years ago

In past, I was trying to integrate glib's and gevent's event loop, and unfortunately I've failed. I guess I should try again.

I think that the best way would be to run glib's event loop and everything glib-related in another thread, and use event queues to synchronize it.

ghost commented 7 years ago

Alright thanks for the tipp, i will try to do that. =)

LEW21 commented 7 years ago

This week I'll release version with support for gevent's event loop - so it'll work with all gevent-based webservers (like gunicorn -k gevent).

ghost commented 7 years ago

Would be pretty cool If I can replace the threading with the gevent loop!

ghost commented 7 years ago

Does the greenglib-dev branch already work? I pulled it, made a setup and installed it hoping it works :P

So far I was able to run the flask application with the gevent's WSGIServer. Then I tried to emit a signal but it gave me following error:

File "/home/burak/.local/lib/python3.5/site-packages/pydbus/registration.py", line 125, in func
    bus.con.emit_signal(None, path, interface_name, signal_name, parameters)
TypeError: emit_signal() takes 5 positional arguments but 6 were given

My sample code looks like this: server.py

class BusManager(object):

  """
    <node>
      <interface name='de.my.bus.manager'>
        <method name='foo'>
          <arg type='s' name='param' direction='in'/>
        </method>
        <signal name='sigManager'>
          <arg type='s' name='message' direction='out'/>
        </signal>
      </interface>
    </node>
  """
  sigManager = signal()
  def foo(self, param):
    sigManager.emit("Foo called with param '{}'.".format(param))

def run():
  while True:
    gevent.sleep(seconds=0.05)

bus = SessionBus()
bus.publish("de.my.bus", BusManager)
loop = Greenlet.spawn(run)
loop.join()

client.py

class Client:
  def __init__(self):
    self.bus = SessionBus()
    self.manager = self.bus.get("de.my.bus")
    self.manager.sigManager.connect(self.onSigManager)
    self.loop = Greenlet(self.run)

  def onSigManager(self, message):
    print("Signal was emitted with message: {}".format(message), flush=True)

  def foo(self, param): # this is called via http request
    self.manager.foo(param)

  def run(self):
    while True:
      gevent.sleep(seconds=0.05)

main.py

client = Client()
app = Flask(__name__)
app.debug = False

if __name__ == '__main__':
    http_server = WSGIServer(('', 5000), app)
    client.loop.start()
    wsgi = Greenlet.spawn(http_server.serve_forever)
    gevent.joinall([client.loop, wsgi])
LEW21 commented 7 years ago

Works for most cases, looks like I didn't test signals. Fixed in https://github.com/LEW21/pydbus/commit/05ee9e946f991eab74ca2e13a74716ee2c2c5974.

I didn't merge it yet because I'm thinking about integrating greenglib with pgi in some way, but I guess that would be a long term project, and I should just release the code I have.

(Note that I'm not sure if I'm going to merge the Python 2 unicode patch.)

BTW, I don't think the Client.run() loop is necessary, I think gevent is able to handle external (pydbus-sent) events while the control is in serve_forever().

ghost commented 7 years ago

I've tested it, everything works so far now. The Client.run() loop was in fact not necessary. Thanks! I'll close the issue now and reopen it when I find any bugs.

Greetings

ghost commented 7 years ago

I hoped you would include the greenlib stuff in the next release but you didn't. Is there a reason why?

LEW21 commented 7 years ago

I've wanted to release 0.6 with stable features only, and I want to work on greenlib a bit more. I hope to return to it this month.

vilhalmer commented 5 years ago

Any chance this branch can be brought back to life? I was able to rebase it on top of master and run the tests without too much trouble.

Edit: looks like there's a bit of async cleanup to be done for python 3.7, and some gevent api changes.