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

ValueError: write to closed file when downloading a playlist and outputting to stdout #3686

Closed
dstftw opened this issue Sep 5, 2014 · 0 comments

Comments

@dstftw
Copy link
Collaborator

@dstftw dstftw commented Sep 5, 2014

Submitted by a____ @ freenode:

ValueError: write to closed file in youtube_dl/youtube_dl/downloader/http.py, line 159, "stream.write(data_block)"

This error is raised when downloading a playlist and outputting to stdout.

Command line:
youtube-dl -o '-' <playlist-url>

Cause:
It looks like this error is caused by an unconditional close in http.py line 196. The close works fine for normal files because they are only opened once, but causes the error for sys.stdout because it is reused and can't be reopened.

Sort-of visualization:

Downloaded File 1:

    Line 151: (stream, tmpfilename) = sanitize_open(tmpfilename, open_mode)
    stream is now an open sys.stdout
    Line 196: stream.close()
    stream is now a closed sys.stdout

Downloaded File 2:

    Line 151: (stream, tmpfilename) = sanitize_open(tmpfilename, open_mode)
    stream still is closed
    Line 159: stream.write(data_block)
    ^ error, writing to closed sys.stdout

Proposed fix:

Add a check whether stream is sys.stdout/sys.stdout.buffer.

Diff of proposed fix:

--- http_old.py
+++ http.py
@@ -1,6 +1,7 @@
 import os
 import time
+import sys

 from .common import FileDownloader
 from ..utils import (
     compat_urllib_request,
@@ -192,9 +193,10 @@
         if stream is None:
             self.to_stderr(u"\n")
             self.report_error(u'Did not get any data blocks')
             return False
-        stream.close()
+        if stream is not sys.stdout and (hasattr(sys.stdout, 'buffer') and stream is not sys.stdout.buffer):
+            stream.close()
         self.report_finish(data_len_str, (time.time() - start))
         if data_len is not None and byte_counter != data_len:
             raise ContentTooShortError(byte_counter, int(data_len))
         self.try_rename(tmpfilename, filename)
@dstftw dstftw closed this in 88a23ae Sep 5, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
1 participant
You can’t perform that action at this time.