[Train] Allow contextlib.redirect_stdout() to bypass print redirect to logs#61075
Conversation
redirect_stdout() replaces sys.stdout with a StringIO, but redirected_print was unconditionally sending to the logger when file was stdout or None. now it checks whether stdout/stderr have been redirected and falls back to the original print if so. also fixes _original_print(objects, ...) -> _original_print(*objects, ...) which was wrapping args in a tuple on the custom-file path. Fixes ray-project#61050
There was a problem hiding this comment.
Code Review
This pull request correctly fixes an issue where the patched print function in Ray Train would interfere with contextlib.redirect_stdout(). The fix involves checking if sys.stdout or sys.stderr have been redirected and, if so, falling back to the original print function. A new test case has been added to verify this behavior. Additionally, a minor bug related to argument unpacking in the call to the original print function is also fixed. The changes are logical and well-implemented. I've added one suggestion to make the code slightly more concise.
|
This pull request has been automatically marked as stale because it has not had You can always ask for help on our discussion forum or Ray's public slack channel. If you'd like to keep this open, just leave any comment, and the stale label will be removed. |
|
This pull request has been automatically closed because there has been no more activity in the 14 days Please feel free to reopen or open a new pull request if you'd still like this to be addressed. Again, you can always ask for help on our discussion forum or Ray's public slack channel. Thanks again for your contribution! |
Signed-off-by: matthewdeng <matt@anyscale.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Reviewed by Cursor Bugbot for commit a10bcb2. Configure here.
pseudo-rnd-thoughts
left a comment
There was a problem hiding this comment.
Thanks for the PR, overall looks good. Could you just merge the two if statements and add to the test
Signed-off-by: Mark Towers <mark@anyscale.com>
contextlib.redirect_stdout() to bypass print redirect to logs
Signed-off-by: Mark Towers <mark.m.towers@gmail.com>
Signed-off-by: Mark Towers <mark.m.towers@gmail.com>
… to logs (ray-project#61075) When Ray Train's print patch is active, any library that uses `contextlib.redirect_stdout()` to capture print output gets broken — the patched `redirected_print` sends everything to the logger unconditionally when `file` is `stdout` or `None`, even if stdout has been replaced by a `StringIO` via `redirect_stdout()`. This is what happens with `smart_open`, which builds its docstring by capturing print output at import time. On Ray workers the print patch runs first, so when smart_open gets imported later as a transitive dep, the docstring text ends up in the logger instead of being captured. The fix checks whether `sys.stdout`/`sys.stderr` have been redirected (i.e. they're not `sys.__stdout__`/`sys.__stderr__`) and falls back to the original print in that case. This way `redirect_stdout()` works as expected while normal prints still get routed through the logger. Also fixed a minor bug on the custom-file fallback path where `_original_print(objects, ...)` was missing the `*` unpack (should be `_original_print(*objects, ...)`). Fixes ray-project#61050 --------- Signed-off-by: matthewdeng <matt@anyscale.com> Signed-off-by: Mark Towers <mark@anyscale.com> Signed-off-by: Mark Towers <mark.m.towers@gmail.com> Co-authored-by: matthewdeng <matt@anyscale.com> Co-authored-by: Mark Towers <mark@anyscale.com> Co-authored-by: Mark Towers <mark.m.towers@gmail.com>
… to logs (ray-project#61075) When Ray Train's print patch is active, any library that uses `contextlib.redirect_stdout()` to capture print output gets broken — the patched `redirected_print` sends everything to the logger unconditionally when `file` is `stdout` or `None`, even if stdout has been replaced by a `StringIO` via `redirect_stdout()`. This is what happens with `smart_open`, which builds its docstring by capturing print output at import time. On Ray workers the print patch runs first, so when smart_open gets imported later as a transitive dep, the docstring text ends up in the logger instead of being captured. The fix checks whether `sys.stdout`/`sys.stderr` have been redirected (i.e. they're not `sys.__stdout__`/`sys.__stderr__`) and falls back to the original print in that case. This way `redirect_stdout()` works as expected while normal prints still get routed through the logger. Also fixed a minor bug on the custom-file fallback path where `_original_print(objects, ...)` was missing the `*` unpack (should be `_original_print(*objects, ...)`). Fixes ray-project#61050 --------- Signed-off-by: matthewdeng <matt@anyscale.com> Signed-off-by: Mark Towers <mark@anyscale.com> Signed-off-by: Mark Towers <mark.m.towers@gmail.com> Co-authored-by: matthewdeng <matt@anyscale.com> Co-authored-by: Mark Towers <mark@anyscale.com> Co-authored-by: Mark Towers <mark.m.towers@gmail.com> Signed-off-by: anindyam1969 <amukherjee@kinetica.com>
… to logs (ray-project#61075) When Ray Train's print patch is active, any library that uses `contextlib.redirect_stdout()` to capture print output gets broken — the patched `redirected_print` sends everything to the logger unconditionally when `file` is `stdout` or `None`, even if stdout has been replaced by a `StringIO` via `redirect_stdout()`. This is what happens with `smart_open`, which builds its docstring by capturing print output at import time. On Ray workers the print patch runs first, so when smart_open gets imported later as a transitive dep, the docstring text ends up in the logger instead of being captured. The fix checks whether `sys.stdout`/`sys.stderr` have been redirected (i.e. they're not `sys.__stdout__`/`sys.__stderr__`) and falls back to the original print in that case. This way `redirect_stdout()` works as expected while normal prints still get routed through the logger. Also fixed a minor bug on the custom-file fallback path where `_original_print(objects, ...)` was missing the `*` unpack (should be `_original_print(*objects, ...)`). Fixes ray-project#61050 --------- Signed-off-by: matthewdeng <matt@anyscale.com> Signed-off-by: Mark Towers <mark@anyscale.com> Signed-off-by: Mark Towers <mark.m.towers@gmail.com> Co-authored-by: matthewdeng <matt@anyscale.com> Co-authored-by: Mark Towers <mark@anyscale.com> Co-authored-by: Mark Towers <mark.m.towers@gmail.com>

When Ray Train's print patch is active, any library that uses
contextlib.redirect_stdout()to capture print output gets broken — the patchedredirected_printsends everything to the logger unconditionally whenfileisstdoutorNone, even if stdout has been replaced by aStringIOviaredirect_stdout().This is what happens with
smart_open, which builds its docstring by capturing print output at import time. On Ray workers the print patch runs first, so when smart_open gets imported later as a transitive dep, the docstring text ends up in the logger instead of being captured.The fix checks whether
sys.stdout/sys.stderrhave been redirected (i.e. they're notsys.__stdout__/sys.__stderr__) and falls back to the original print in that case. This wayredirect_stdout()works as expected while normal prints still get routed through the logger.Also fixed a minor bug on the custom-file fallback path where
_original_print(objects, ...)was missing the*unpack (should be_original_print(*objects, ...)).Fixes #61050