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

Broken pipe on piping list output on Python 3 #2622

Closed
xeals opened this issue Jul 5, 2017 · 3 comments · Fixed by #2631
Closed

Broken pipe on piping list output on Python 3 #2622

xeals opened this issue Jul 5, 2017 · 3 comments · Fixed by #2631
Labels
bug bugs that are confirmed and actionable python 3 Arises from the Python 2->3 transition.

Comments

@xeals
Copy link

xeals commented Jul 5, 2017

Problem

I'm trying to write a quick dirty script to play the first result of a search, looking much like you'd expect:

mpv --no-audio-display "$(beet ls -p $@ | head -n 1)"

However, there's something in the formatting of the output that head doesn't like:

$ beet ls -p home
/media/beets/5 Seconds of Summer/5 Seconds of Summer/09 Long Way Home.mp3
/media/beets/5 Seconds of Summer/LIVESOS/07 Long Way Home.mp3
/media/beets/5 Seconds of Summer/Sounds Good Feels Good/12 Broken Home.mp3
/media/beets/American Authors/What We Live For/07 Go Big or Go Home.mp3
/media/beets/Boys Like Girls/Crazy World/09 Take Me Home.mp3
...

However

beet -vv ls -p home | head -n 1                                                                                                                                                                   user configuration: /home/shagaru/.config/beets/config.yaml
data directory: /home/shagaru/.config/beets
plugin paths: 
Sending event: pluginload
library database: /media/Music/library.db
library directory: /media/Music
Sending event: library_opened
/media/beets/5 Seconds of Summer/5 Seconds of Summer/09 Long Way Home.mp3
Exception ignored in: <_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'>
BrokenPipeError: [Errno 32] Broken pipe

Trying to cheat and run it through echo instead produces the following:

$ echo -e $(beet ls -p home) | head -n 1
/media/beets/5 Seconds of Summer/5 Seconds of Summer/09 Long Way Home.mp3 /media/beets/5 Seconds of Summer/LIVESOS/07 Long Way Home.mp3 /media/beets/5 Seconds of Summer/Sounds Good Feels Good/12 Broken Home.mp3 /media/beets/American Authors/What We Live For/07 Go Big or Go Home.mp3 /media/beets/Boys Like Girls/Crazy World/09 Take Me Home.mp3 ...

as one string, so it seems like the proper line-ending characters aren't being properly generated. This may be expected of Python output, I don't know; I haven't written using it.

End question I suppose is there any way around how Python handles printing lines short of rewriting that entire part of the program?

Setup

  • OS: GNU/Linux
  • Python version: 3.5.2
  • beets version: 1.4.4
  • Turning off plugins made problem go away (yes/no): no

My configuration (output of beet config) shouldn't matter, because it's a question of how the program functions inherently.

@sampsyo sampsyo added bug bugs that are confirmed and actionable python 3 Arises from the Python 2->3 transition. labels Jul 5, 2017
@sampsyo sampsyo changed the title Broken pipe on piping list output Broken pipe on piping list output on Python 3 Jul 5, 2017
@sampsyo
Copy link
Member

sampsyo commented Jul 5, 2017

Thank you! I can reproduce this, and it looks like it's a new problem on Python 3. We actually have a specific exception handler for closed pipes on Python 2, but the same technique apparently doesn't work on Python 3. I don't fully understand what's going on with the "Exception ignored" mechanism… some further digging is required here.

@nathdwek
Copy link
Member

nathdwek commented Jul 12, 2017

Reading https://stackoverflow.com/a/26738736, and testing it, it seems replacing pass in the linked snippet with sys.stderr.close() solves this issue.

I don't know if it could hide useful information in the future though. I think it won't since this is for a very specific errno.

@Azphreal could you check that the branch Fix-2622 works on your end as well?
@sampsyo should we maybe flush stderr before closing it so that no error is mistakenly binned?

nathdwek pushed a commit that referenced this issue Jul 12, 2017
For some reason Python always warns about a BrokenPipeError on
stderr even if it is caught.

Fixes #2622
@sampsyo
Copy link
Member

sampsyo commented Jul 12, 2017

Huh! Wow! Thanks for looking into it—this isn't precisely what I expected, but it makes sense. I suppose the problem is that just ignoring the exception caused some sort of internal exception handler to trigger, which can't produce anything because the output streams are already shutting down. Closing the pipe avoids that.

This does indeed looks like the right fix; let's do it! ✨

I believe an extra flush should probably be unnecessary—each write we do to stderr should be followed by a flush already. For example, the main thing we do is call logging to write lines to stderr; that flushes after every logging call. I could be proven wrong, but I think we're fine to just close.

nathdwek added a commit that referenced this issue Jul 22, 2017
Do not warn about a BrokenPipeError we do consider - Fix #2622
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug bugs that are confirmed and actionable python 3 Arises from the Python 2->3 transition.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants