Search code examples
pythonpython-3.xstomp

Python script skips certain lines when run without shell


I have some code like this:

from stomp import *
from stomp.listener import ConnectionListener
from stomp.utils import parse_frame

class MyListener(ConnectionListener):
  _counter=0
  def on_message(self, frame):
    if self._counter > 10:
      return
    print(self._counter)
    self._counter += 1

print('Starting...')
connection = Connection([('darwin-dist-44ae45.nationalrail.co.uk', '61613')])
connection.set_listener('', MyListener())
connection.connect(REDACTED)
connection.subscribe('/topic/darwin.pushport-v16', 11)
print('Ummm...???')

When I run this from command line using Python, the lines with connection don't execute:

$ python3 myscript.py                                                                                                                                       
Starting...
Ummm...???

However, when I open python shell and run these commands one by one, the connection.subscribe('/topic/darwin.pushport-v16', 11) produces a bunch of output as expected:

$ python3
>>> from stomp import *
>>> from stomp.listener import ConnectionListener
>>> from stomp.utils import parse_frame
>>> 
>>> class MyListener(ConnectionListener):
...   _counter=0
...   def on_message(self, frame):
...     if self._counter > 10:
...       return
...     print(self._counter)
...     self._counter += 1
... 
>>> print('Starting...')
Starting...
>>> connection = Connection([('darwin-dist-44ae45.nationalrail.co.uk', '61613')])
>>> connection.set_listener('', MyListener())
>>> connection.connect(REDACTED)
>>> connection.subscribe('/topic/darwin.pushport-v16', 11)
0
1
2

I have never encountered odd behavior like this before. Why is this happening and how do I fix it? thanks


Solution

  • I believe the problem is that nothing is keeping your application from exiting. Therefore, it has no time to actually receive any messages. However, when you run it from the Python shell it has time to receive messages and print the counter.

    Try something like this:

    import time
    from stomp import *
    from stomp.listener import ConnectionListener
    from stomp.utils import parse_frame
    
    class MyListener(ConnectionListener):
      _counter=0
      def on_message(self, frame):
        if self._counter > 10:
          return
        print(self._counter)
        self._counter += 1
    
    print('Starting...')
    connection = Connection([('darwin-dist-44ae45.nationalrail.co.uk', '61613')])
    connection.set_listener('', MyListener())
    connection.connect(REDACTED)
    connection.subscribe('/topic/darwin.pushport-v16', 11)
    print('Ummm...???')
    time.sleep(30)
    connection.disconnect()
    

    It's important to keep in mind that the MyListener instance set on connection when invoking set_listener will be invoked asynchronously when a message arrives on the queue. In other words, the client won't simply wait/block until a message arrives. Therefore, something needs to keep the consumer alive for a bit waiting for a message. If a message arrives during this 30 second sleep then the MyListener will receive it and print the counter. If a message doesn't arrive on the queue then the MyListener won't be invoked and the application will simply terminate.