ROS2 Launch not interleaving stdout?

I’m trying to learn how to use ROS2 Launch. I thought I had it figured out after looking at some examples, but I’ve got a weird issue: it’s not interleaving stdout.

Let me explain. I’m using beta3. I have a simple talker in C++, and a listener in Python. I can run the talker in one terminal:

$ ros2 run talker_cpp talker
Hello world 0
Hello world 1
Hello world 2
Hello world 3

And the listener in another:

$ ros2 run listener_py listener
I heard: Hello world 0
I heard: Hello world 1
I heard: Hello world 2
I heard: Hello world 3

Pretty straight-forward. Okay, so I write the following launch script:

from ros2run.api import get_executable_path


def launch(launch_descriptor, argv):
    ld = launch_descriptor
    ld.add_process(
        cmd=[get_executable_path(package_name='talker_cpp', executable_name='talker')],
        name='talker',
    )
    ld.add_process(
        cmd=[get_executable_path(package_name='listener_py', executable_name='listener')],
        name='listener',
    )

    return ld

Couldn’t be simpler. Now I run it:

$ launch $(ros2 pkg prefix listener_py)/share/listener_py/launch/talk_and_listen.py
(talker) pid 26484: ['/home/ubuntu/my_ws/install/lib/talker_cpp/talker'] (stderr > stdout, all > console)
(listener) pid 26485: ['/home/ubuntu/my_ws/install/lib/listener_py/listener'] (stderr > stdout, all > console)
[talker] Hello world 0
[talker] Hello world 1
[talker] Hello world 2
[talker] Hello world 3
[talker] Hello world 4
[talker] Hello world 5
[talker] Hello world 6
^C(talker) signal SIGINT
(listener) signal SIGINT
[listener] I heard: Hello world 1
[listener] I heard: Hello world 2
[listener] I heard: Hello world 3
[listener] I heard: Hello world 4
[listener] I heard: Hello world 5
[listener] I heard: Hello world 6
[listener] Traceback (most recent call last):
[listener]   File "/home/ubuntu/my_ws/install/lib/listener_py/listener", line 9, in <module>
[listener]     load_entry_point('listener-py==0.0.0', 'console_scripts', 'listener')()
[listener]   File "/home/ubuntu/my_ws/install/lib/python3.5/site-packages/nodes/listener.py", line 16, in main
[listener]     rclpy.spin(node)
[listener]   File "/home/ubuntu/ros2_ws/install/lib/python3.5/site-packages/rclpy/__init__.py", line 48, in spin
[listener]     executor.spin_once()
[listener]   File "/home/ubuntu/ros2_ws/install/lib/python3.5/site-packages/rclpy/executors.py", line 382, in spin_once
[listener]     handler, entity, node = next(self.wait_for_ready_callbacks(timeout_sec=timeout_sec))
[listener]   File "/home/ubuntu/ros2_ws/install/lib/python3.5/site-packages/rclpy/executors.py", line 333, in wait_for_ready_callbacks
[listener] KeyboardInterrupt
[talker] signal_handler(2)
[talker] signal_handler(2)
(talker) rc 0
(listener) rc 1

Take careful note: you see the stdout from the talker ONLY. Once I ctrl+c it, THEN all the stdout from the listener comes through. I expected the stdout from each to be interleaved. Is that an unreasonable expectation, or is something weird happening? There’s nothing particularly special about either the talker or the listener, although I’m of course happy to share them if necessary.

The problem might just be due to the way you invoke the processes. Python will by default perform output buffering. You might want to try forcing unbuffered output by e.g. setting the environment variable PYTHONUNBUFFERED.

Thanks @dirk-thomas, you’re right, that causes things to work the way I expect. This was not necessary in the ROS1 world, did roslaunch happen to set this itself? Is this perhaps something that belongs in ros2’s launch?

Not that I know of .