GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
GeezerVison is showing github.com — gh-87597: Decode subprocess output in text mode when timeout is hit by LewisGaul · Pull Request #95579 · python/cpython Conversation
|
|
I'm not sure why this is failing on MacOS, I would've expected it to follow the posix code paths, but I don't know much about mac... Any suggestions? |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
|
Any chance of a review @eryksun? :) Do we think the fix should be backported, since it's marked as a bug? It would be great to get this in 3.9 so I can remove a workaround I currently have in place! |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| encoding, | ||
| errors) | ||
| else: | ||
| raise |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
This exception would be raised instead of the timeout error, which isn't going to be helpful. I considered three alternatives, but I think the last is the best:
from itTimeoutExpired class (so it learns to keep encoding/errors around and do the decode on demand)exc.start here, then decode the rest with the replace error handler and concatenate it
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Agreed, I like that latter strategy. I think it is important to have the TimeoutExpired be the primary error. Otherwise the caller could wrongly interpret the UnicodeDecodeError as the process exiting naturally while producing undecodable output. If the process did emit undecodable data on its own, that isn't important in this situation.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| if stdout_seq is not None: | ||
| stdout = b''.join(stdout_seq) | ||
| if self.text_mode: | ||
| stdout = translate_newlines_partial_output( | ||
| stdout, self.stdout.encoding, self.stdout.errors) | ||
| else: | ||
| stdout = None |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Maybe this whole pattern could go into the helper function? join_and_translate_newlines?
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
I think the if/else around the None makes sense here as is, but the join and text_mode conditional could be done in-function.
basically
def join_and_maybe_decode(output_seq, data, encoding, errors): output = b''.join(output_seq) if self.text_mode: try: ... # existing translate_newlines_partial_output code
and here you'd have things like
if stdout_seq is not None: stdout = join_and_maybe_decode(stdout_seq, data, encoding, errors) else: stdout = None # and the same for stderr
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| encoding, | ||
| errors) | ||
| else: | ||
| raise |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Agreed, I like that latter strategy. I think it is important to have the TimeoutExpired be the primary error. Otherwise the caller could wrongly interpret the UnicodeDecodeError as the process exiting naturally while producing undecodable output. If the process did emit undecodable data on its own, that isn't important in this situation.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| if stdout_seq is not None: | ||
| stdout = b''.join(stdout_seq) | ||
| if self.text_mode: | ||
| stdout = translate_newlines_partial_output( | ||
| stdout, self.stdout.encoding, self.stdout.errors) | ||
| else: | ||
| stdout = None |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
I think the if/else around the None makes sense here as is, but the join and text_mode conditional could be done in-function.
basically
def join_and_maybe_decode(output_seq, data, encoding, errors): output = b''.join(output_seq) if self.text_mode: try: ... # existing translate_newlines_partial_output code
and here you'd have things like
if stdout_seq is not None: stdout = join_and_maybe_decode(stdout_seq, data, encoding, errors) else: stdout = None # and the same for stderr
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| stdout, stderr = popen.communicate(input='') | ||
| self.assertEqual(stdout, '1\n2\n3\n4') | ||
|
|
||
| @unittest.skipIf(mswindows, "behavior currently not supported on Windows") |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
what is needed for this to work on Windows?
having inconsistent behavior in the returned stderr/stdout types on Timeout between the two platforms will make people's code difficult.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Hah, I didn't even notice this.
I'm guessing this should actually be "platforms that don't default to UTF-8 don't trigger the decoding error", which luckily is easily resolved by explicitly specifying that the encoding should be utf-8.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated. Once you have made the requested changes, please leave a comment on this pull request containing the phrase |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
We cannot. I don't even think we can accept this as written today without a deprecation period as this is changing a public API so that makes this a feature. People have already written code less pedantic than your own isinstance checking example that blindly assumes on TimeoutExpired that the stdout/stderr data is bytes or None. So this is an API change that breaks code in existing releases. That also means we cannot accept this behavior change for 3.12 and need to modify this PR to either:
Whatever behavior we have needs to become consistent across platforms as well. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
This is true. What we might be able to do now is to make This is safe enough, because all versions will support setting that attribute, it just won't have any effect on old ones. We can then also show a deprecation warning for accessing the attributes without setting |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
This PR is stale because it has been open for 30 days with no activity. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
Successfully merging this pull request may close these issues.
There was an error while loading. Please reload this page.