Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make the ros2cli output always line buffered #659

Merged
merged 4 commits into from
Aug 13, 2021

Conversation

ivanpauno
Copy link
Member

Fixes #595.

This forces all calls to print() to also flush the output buffer, the result is similar to having line buffering.

Alternative: We could also do something like what it's suggested here https://stackoverflow.com/questions/107705/disable-output-buffering.

Another alternative: I don't think we need unbuffered output for all commands though, e.g. it's not needed for ros2 topic list.
The ones that need unbuffered (or line buffered) output are the ones that are periodically reporting progress, e.g. ros2 topic pub, ros2 topic echo, etc.
Some of that output could arguably be going to stderr, which in python is always line buffered (even when non interactive), e.g. the output of ros2 topic pub.
The output of ros2 topic echo should probably go to stdout though, and if we don't want global line buffering we would need to pass the flush argument manually.

See also:

Signed-off-by: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>
@ivanpauno ivanpauno added the enhancement New feature or request label Aug 11, 2021
@ivanpauno ivanpauno self-assigned this Aug 11, 2021
Copy link
Contributor

@hidmic hidmic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the approach, but it'd be nice to have a way to toggle that flag (e.g. an envvar, a CLI argument, take your pick).

@ivanpauno
Copy link
Member Author

I like the approach, but it'd be nice to have a way to toggle that flag (e.g. an envvar, a CLI argument, take your pick).

I can add that, but I'm not sure why someone would want to use it.
do you have an use case in mind?

Copy link
Contributor

@clalancette clalancette left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the approach. The only real reason to allow disabling of flushing is for performance, but I actually don't think that is super important here.

I think we should run full CI on this, just to make sure something above this package doesn't break.

Finally, when we do merge this I'll request a note on https://github.com/ros2/ros2_documentation/blob/rolling/source/Releases/Release-Humble-Hawksbill.rst , since it is a change in behavior.

@wjwwood
Copy link
Member

wjwwood commented Aug 11, 2021

After talking offline about it, the use case I think is steaming relatively high bandwidth data from echo into a file for processing later. In that case performance could be an issue. So I'm with @hidmic and there should be a way to "undo" our always-unbuffered magic.

…figure()

Signed-off-by: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>
@ivanpauno
Copy link
Member Author

I have made two changes:

  • Added an argument to disable line buffering.
  • Use TextIoWrapper.reconfigure() instead of patching print().
    The advantage is that only affects stdout, and not print() to other files.
    stdout is documented to be a FileObject as returned by open(), and open() docs say that they return a TextIoWrapper instance for files in text mode (which stdout always is).
    So I would assume that means that stdout is always a TextIoWrapper instance with a reconfigure() method (except if someone patched sys.stdout with a StringIO stream before, which cannot happen here).

@ivanpauno
Copy link
Member Author

Use TextIoWrapper.reconfigure() instead of patching print().

I noticed while writing this that that method was added in python 3.7, and we still support python 3.6.
So, I will add a fallback mechanism to support line buffering (or use the previous print() patch).

Signed-off-by: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>
Copy link
Member

@wjwwood wjwwood left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@ivanpauno
Copy link
Member Author

CI:

  • Linux Build Status
  • Linux-aarch64 Build Status
  • macOS Build Status
  • Windows Build Status

@ivanpauno
Copy link
Member Author

Windows failure is unrelated

Copy link
Contributor

@clalancette clalancette left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two nits inline, but I'm going to approve anyway.

ros2cli/ros2cli/cli.py Show resolved Hide resolved
ros2cli/ros2cli/cli.py Outdated Show resolved Hide resolved
Copy link
Member

@jacobperron jacobperron left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm with Chris's comments addressed.

Signed-off-by: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>
@ivanpauno ivanpauno merged commit 0075a71 into master Aug 13, 2021
@delete-merged-branch delete-merged-branch bot deleted the ivanpauno/make-output-line-buffered branch August 13, 2021 17:45
except AttributeError:
# if stdout is not a TextIoWrapper instance, or we're using python older than 3.7,
# force line buffering by patching print
builtins.print = functools.partial(print, flush=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ivanpauno FYI if the decorator monitors the file keyword argument of print, you can limit its action to sys.stdout.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

true, I didn't feel that was really needed though.
do you think we need a patch for this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, it's unlikely anyone will ever hit it before Python 3.6 support is gone.

fujitatomoya added a commit to fujitatomoya/ros2cli that referenced this pull request Aug 14, 2021
fujitatomoya added a commit to fujitatomoya/ros2cli that referenced this pull request Aug 14, 2021
This reverts commit 0075a71.

Signed-off-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
@fujitatomoya
Copy link
Collaborator

This breaks the CI for ros2param (see https://ci.ros2.org/job/ci_linux/15050/testReport/junit/ros2param.ros2param.test/test_verb_dump/test_verb_dump/), we need to revert this now.

fujitatomoya added a commit that referenced this pull request Aug 14, 2021
This reverts commit 0075a71.

Signed-off-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
ivanpauno added a commit that referenced this pull request Aug 17, 2021
…660)"

This reverts commit 0102a4e.

Signed-off-by: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>
ivanpauno added a commit that referenced this pull request Aug 18, 2021
Signed-off-by: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Disable output buffering by default
6 participants