@ -49,6 +49,7 @@ from .utils import (
date_from_str ,
date_from_str ,
DateRange ,
DateRange ,
DEFAULT_OUTTMPL ,
DEFAULT_OUTTMPL ,
OUTTMPL_TYPES ,
determine_ext ,
determine_ext ,
determine_protocol ,
determine_protocol ,
DOT_DESKTOP_LINK_TEMPLATE ,
DOT_DESKTOP_LINK_TEMPLATE ,
@ -182,7 +183,8 @@ class YoutubeDL(object):
format_sort_force : Force the given format_sort . see " Sorting Formats " for more details .
format_sort_force : Force the given format_sort . see " Sorting Formats " for more details .
allow_multiple_video_streams : Allow multiple video streams to be merged into a single file
allow_multiple_video_streams : Allow multiple video streams to be merged into a single file
allow_multiple_audio_streams : Allow multiple audio streams to be merged into a single file
allow_multiple_audio_streams : Allow multiple audio streams to be merged into a single file
outtmpl : Template for output names .
outtmpl : Dictionary of templates for output names . Allowed keys
are ' default ' and the keys of OUTTMPL_TYPES ( in utils . py )
outtmpl_na_placeholder : Placeholder for unavailable meta fields .
outtmpl_na_placeholder : Placeholder for unavailable meta fields .
restrictfilenames : Do not allow " & " and spaces in file names
restrictfilenames : Do not allow " & " and spaces in file names
trim_file_name : Limit length of filename ( extension excluded )
trim_file_name : Limit length of filename ( extension excluded )
@ -493,10 +495,7 @@ class YoutubeDL(object):
' Set the LC_ALL environment variable to fix this. ' )
' Set the LC_ALL environment variable to fix this. ' )
self . params [ ' restrictfilenames ' ] = True
self . params [ ' restrictfilenames ' ] = True
if isinstance ( params . get ( ' outtmpl ' ) , bytes ) :
self . outtmpl_dict = self . parse_outtmpl ( )
self . report_warning (
' Parameter outtmpl is bytes, but should be a unicode string. '
' Put from __future__ import unicode_literals at the top of your code file or consider switching to Python 3.x. ' )
self . _setup_opener ( )
self . _setup_opener ( )
@ -732,8 +731,21 @@ class YoutubeDL(object):
except UnicodeEncodeError :
except UnicodeEncodeError :
self . to_screen ( ' Deleting already existent file ' )
self . to_screen ( ' Deleting already existent file ' )
def prepare_filename ( self , info_dict , warn = False ) :
def parse_outtmpl ( self ) :
""" Generate the output filename. """
outtmpl_dict = self . params . get ( ' outtmpl ' , { } )
if not isinstance ( outtmpl_dict , dict ) :
outtmpl_dict = { ' default ' : outtmpl_dict }
outtmpl_dict . update ( {
k : v for k , v in DEFAULT_OUTTMPL . items ( )
if not outtmpl_dict . get ( k ) } )
for key , val in outtmpl_dict . items ( ) :
if isinstance ( val , bytes ) :
self . report_warning (
' Parameter outtmpl is bytes, but should be a unicode string. '
' Put from __future__ import unicode_literals at the top of your code file or consider switching to Python 3.x. ' )
return outtmpl_dict
def _prepare_filename ( self , info_dict , tmpl_type = ' default ' ) :
try :
try :
template_dict = dict ( info_dict )
template_dict = dict ( info_dict )
@ -765,7 +777,8 @@ class YoutubeDL(object):
na = self . params . get ( ' outtmpl_na_placeholder ' , ' NA ' )
na = self . params . get ( ' outtmpl_na_placeholder ' , ' NA ' )
template_dict = collections . defaultdict ( lambda : na , template_dict )
template_dict = collections . defaultdict ( lambda : na , template_dict )
outtmpl = self . params . get ( ' outtmpl ' , DEFAULT_OUTTMPL )
outtmpl = self . outtmpl_dict . get ( tmpl_type , self . outtmpl_dict [ ' default ' ] )
force_ext = OUTTMPL_TYPES . get ( tmpl_type )
# For fields playlist_index and autonumber convert all occurrences
# For fields playlist_index and autonumber convert all occurrences
# of %(field)s to %(field)0Nd for backward compatibility
# of %(field)s to %(field)0Nd for backward compatibility
@ -835,6 +848,9 @@ class YoutubeDL(object):
# title "Hello $PATH", we don't want `$PATH` to be expanded.
# title "Hello $PATH", we don't want `$PATH` to be expanded.
filename = expand_path ( outtmpl ) . replace ( sep , ' ' ) % template_dict
filename = expand_path ( outtmpl ) . replace ( sep , ' ' ) % template_dict
if force_ext is not None :
filename = replace_extension ( filename , force_ext , template_dict . get ( ' ext ' ) )
# https://github.com/blackjack4494/youtube-dlc/issues/85
# https://github.com/blackjack4494/youtube-dlc/issues/85
trim_file_name = self . params . get ( ' trim_file_name ' , False )
trim_file_name = self . params . get ( ' trim_file_name ' , False )
if trim_file_name :
if trim_file_name :
@ -852,25 +868,28 @@ class YoutubeDL(object):
filename = encodeFilename ( filename , True ) . decode ( preferredencoding ( ) )
filename = encodeFilename ( filename , True ) . decode ( preferredencoding ( ) )
filename = sanitize_path ( filename )
filename = sanitize_path ( filename )
return filename
except ValueError as err :
self . report_error ( ' Error in output template: ' + str ( err ) + ' (encoding: ' + repr ( preferredencoding ( ) ) + ' ) ' )
return None
def prepare_filename ( self , info_dict , dir_type = ' ' , warn = False ) :
""" Generate the output filename. """
paths = self . params . get ( ' paths ' , { } )
assert isinstance ( paths , dict )
filename = self . _prepare_filename ( info_dict , dir_type or ' default ' )
if warn and not self . __prepare_filename_warned :
if warn and not self . __prepare_filename_warned :
if not self . params . get ( ' paths ' ) :
if not pa ths:
pass
pass
elif filename == ' - ' :
elif filename == ' - ' :
self . report_warning ( ' --paths is ignored when an outputting to stdout ' )
self . report_warning ( ' --paths is ignored when an outputting to stdout ' )
elif os . path . isabs ( filename ) :
elif os . path . isabs ( filename ) :
self . report_warning ( ' --paths is ignored since an absolute path is given in output template ' )
self . report_warning ( ' --paths is ignored since an absolute path is given in output template ' )
self . __prepare_filename_warned = True
self . __prepare_filename_warned = True
if filename == ' - ' or not filename :
return filename
return filename
except ValueError as err :
self . report_error ( ' Error in output template: ' + str ( err ) + ' (encoding: ' + repr ( preferredencoding ( ) ) + ' ) ' )
return None
def prepare_filepath ( self , filename , dir_type = ' ' ) :
if filename == ' - ' :
return filename
paths = self . params . get ( ' paths ' , { } )
assert isinstance ( paths , dict )
homepath = expand_path ( paths . get ( ' home ' , ' ' ) . strip ( ) )
homepath = expand_path ( paths . get ( ' home ' , ' ' ) . strip ( ) )
assert isinstance ( homepath , compat_str )
assert isinstance ( homepath , compat_str )
subdir = expand_path ( paths . get ( dir_type , ' ' ) . strip ( ) ) if dir_type else ' '
subdir = expand_path ( paths . get ( dir_type , ' ' ) . strip ( ) ) if dir_type else ' '
@ -1041,10 +1060,7 @@ class YoutubeDL(object):
extract_flat = self . params . get ( ' extract_flat ' , False )
extract_flat = self . params . get ( ' extract_flat ' , False )
if ( ( extract_flat == ' in_playlist ' and ' playlist ' in extra_info )
if ( ( extract_flat == ' in_playlist ' and ' playlist ' in extra_info )
or extract_flat is True ) :
or extract_flat is True ) :
self . __forced_printings (
self . __forced_printings ( ie_result , self . prepare_filename ( ie_result ) , incomplete = True )
ie_result ,
self . prepare_filepath ( self . prepare_filename ( ie_result ) ) ,
incomplete = True )
return ie_result
return ie_result
if result_type == ' video ' :
if result_type == ' video ' :
@ -1150,9 +1166,7 @@ class YoutubeDL(object):
return make_dir ( path , self . report_error )
return make_dir ( path , self . report_error )
if self . params . get ( ' writeinfojson ' , False ) :
if self . params . get ( ' writeinfojson ' , False ) :
infofn = replace_extension (
infofn = self . prepare_filename ( ie_copy , ' pl_infojson ' )
self . prepare_filepath ( self . prepare_filename ( ie_copy ) , ' infojson ' ) ,
' info.json ' , ie_result . get ( ' ext ' ) )
if not ensure_dir_exists ( encodeFilename ( infofn ) ) :
if not ensure_dir_exists ( encodeFilename ( infofn ) ) :
return
return
if not self . params . get ( ' overwrites ' , True ) and os . path . exists ( encodeFilename ( infofn ) ) :
if not self . params . get ( ' overwrites ' , True ) and os . path . exists ( encodeFilename ( infofn ) ) :
@ -1168,9 +1182,7 @@ class YoutubeDL(object):
self . report_error ( ' Cannot write playlist metadata to JSON file ' + infofn )
self . report_error ( ' Cannot write playlist metadata to JSON file ' + infofn )
if self . params . get ( ' writedescription ' , False ) :
if self . params . get ( ' writedescription ' , False ) :
descfn = replace_extension (
descfn = self . prepare_filename ( ie_copy , ' pl_description ' )
self . prepare_filepath ( self . prepare_filename ( ie_copy ) , ' description ' ) ,
' description ' , ie_result . get ( ' ext ' ) )
if not ensure_dir_exists ( encodeFilename ( descfn ) ) :
if not ensure_dir_exists ( encodeFilename ( descfn ) ) :
return
return
if not self . params . get ( ' overwrites ' , True ) and os . path . exists ( encodeFilename ( descfn ) ) :
if not self . params . get ( ' overwrites ' , True ) and os . path . exists ( encodeFilename ( descfn ) ) :
@ -1370,7 +1382,7 @@ class YoutubeDL(object):
and (
and (
not can_merge ( )
not can_merge ( )
or info_dict . get ( ' is_live ' , False )
or info_dict . get ( ' is_live ' , False )
or self . params. get ( ' outtmpl ' , DEFAULT_OUTTMPL ) == ' - ' ) )
or self . outtmpl_dict[ ' default ' ] == ' - ' ) )
return (
return (
' best/bestvideo+bestaudio '
' best/bestvideo+bestaudio '
@ -2032,10 +2044,10 @@ class YoutubeDL(object):
info_dict = self . pre_process ( info_dict )
info_dict = self . pre_process ( info_dict )
filename = self . prepare_filename ( info_dict , warn = True )
info_dict [ ' _filename ' ] = full_filename = self . prepare_filename ( info_dict , warn = True )
info_dict [ ' _filename ' ] = full_filename = self . prepare_filepath ( filename )
temp_filename = self . prepare_filename ( info_dict , ' temp ' )
temp_filename = self . prepare_filepath ( filename , ' temp ' )
files_to_move = { }
files_to_move = { }
skip_dl = self . params . get ( ' skip_download ' , False )
# Forced printings
# Forced printings
self . __forced_printings ( info_dict , full_filename , incomplete = False )
self . __forced_printings ( info_dict , full_filename , incomplete = False )
@ -2047,7 +2059,7 @@ class YoutubeDL(object):
# Do nothing else if in simulate mode
# Do nothing else if in simulate mode
return
return
if f ilename is None :
if f ull_f ilename is None :
return
return
def ensure_dir_exists ( path ) :
def ensure_dir_exists ( path ) :
@ -2059,9 +2071,7 @@ class YoutubeDL(object):
return
return
if self . params . get ( ' writedescription ' , False ) :
if self . params . get ( ' writedescription ' , False ) :
descfn = replace_extension (
descfn = self . prepare_filename ( info_dict , ' description ' )
self . prepare_filepath ( filename , ' description ' ) ,
' description ' , info_dict . get ( ' ext ' ) )
if not ensure_dir_exists ( encodeFilename ( descfn ) ) :
if not ensure_dir_exists ( encodeFilename ( descfn ) ) :
return
return
if not self . params . get ( ' overwrites ' , True ) and os . path . exists ( encodeFilename ( descfn ) ) :
if not self . params . get ( ' overwrites ' , True ) and os . path . exists ( encodeFilename ( descfn ) ) :
@ -2078,9 +2088,7 @@ class YoutubeDL(object):
return
return
if self . params . get ( ' writeannotations ' , False ) :
if self . params . get ( ' writeannotations ' , False ) :
annofn = replace_extension (
annofn = self . prepare_filename ( info_dict , ' annotation ' )
self . prepare_filepath ( filename , ' annotation ' ) ,
' annotations.xml ' , info_dict . get ( ' ext ' ) )
if not ensure_dir_exists ( encodeFilename ( annofn ) ) :
if not ensure_dir_exists ( encodeFilename ( annofn ) ) :
return
return
if not self . params . get ( ' overwrites ' , True ) and os . path . exists ( encodeFilename ( annofn ) ) :
if not self . params . get ( ' overwrites ' , True ) and os . path . exists ( encodeFilename ( annofn ) ) :
@ -2116,10 +2124,11 @@ class YoutubeDL(object):
# ie = self.get_info_extractor(info_dict['extractor_key'])
# ie = self.get_info_extractor(info_dict['extractor_key'])
for sub_lang , sub_info in subtitles . items ( ) :
for sub_lang , sub_info in subtitles . items ( ) :
sub_format = sub_info [ ' ext ' ]
sub_format = sub_info [ ' ext ' ]
sub_f ilename = subtitles_filename ( temp_filename , sub_lang , sub_format , info_dict . get ( ' ext ' ) )
sub_f n = self . prepare_filename ( info_dict , ' subtitle ' )
sub_filename _final = subtitles_filename (
sub_filename = subtitles_filename (
self . prepare_filepath ( filename , ' subtitle ' ) ,
temp_filename if not skip_dl else sub_fn ,
sub_lang , sub_format , info_dict . get ( ' ext ' ) )
sub_lang , sub_format , info_dict . get ( ' ext ' ) )
sub_filename_final = subtitles_filename ( sub_fn , sub_lang , sub_format , info_dict . get ( ' ext ' ) )
if not self . params . get ( ' overwrites ' , True ) and os . path . exists ( encodeFilename ( sub_filename ) ) :
if not self . params . get ( ' overwrites ' , True ) and os . path . exists ( encodeFilename ( sub_filename ) ) :
self . to_screen ( ' [info] Video subtitle %s . %s is already present ' % ( sub_lang , sub_format ) )
self . to_screen ( ' [info] Video subtitle %s . %s is already present ' % ( sub_lang , sub_format ) )
files_to_move [ sub_filename ] = sub_filename_final
files_to_move [ sub_filename ] = sub_filename_final
@ -2153,10 +2162,10 @@ class YoutubeDL(object):
( sub_lang , error_to_compat_str ( err ) ) )
( sub_lang , error_to_compat_str ( err ) ) )
continue
continue
if self . params. get ( ' skip_down load' , False ) :
if skip_dl:
if self . params . get ( ' convertsubtitles ' , False ) :
if self . params . get ( ' convertsubtitles ' , False ) :
# subconv = FFmpegSubtitlesConvertorPP(self, format=self.params.get('convertsubtitles'))
# subconv = FFmpegSubtitlesConvertorPP(self, format=self.params.get('convertsubtitles'))
filename_real_ext = os . path . splitext ( f ilename) [ 1 ] [ 1 : ]
filename_real_ext = os . path . splitext ( f ull_f ilename) [ 1 ] [ 1 : ]
filename_wo_ext = (
filename_wo_ext = (
os . path . splitext ( full_filename ) [ 0 ]
os . path . splitext ( full_filename ) [ 0 ]
if filename_real_ext == info_dict [ ' ext ' ]
if filename_real_ext == info_dict [ ' ext ' ]
@ -2176,9 +2185,7 @@ class YoutubeDL(object):
return
return
if self . params . get ( ' writeinfojson ' , False ) :
if self . params . get ( ' writeinfojson ' , False ) :
infofn = replace_extension (
infofn = self . prepare_filename ( info_dict , ' infojson ' )
self . prepare_filepath ( filename , ' infojson ' ) ,
' info.json ' , info_dict . get ( ' ext ' ) )
if not ensure_dir_exists ( encodeFilename ( infofn ) ) :
if not ensure_dir_exists ( encodeFilename ( infofn ) ) :
return
return
if not self . params . get ( ' overwrites ' , True ) and os . path . exists ( encodeFilename ( infofn ) ) :
if not self . params . get ( ' overwrites ' , True ) and os . path . exists ( encodeFilename ( infofn ) ) :
@ -2190,11 +2197,14 @@ class YoutubeDL(object):
except ( OSError , IOError ) :
except ( OSError , IOError ) :
self . report_error ( ' Cannot write video metadata to JSON file ' + infofn )
self . report_error ( ' Cannot write video metadata to JSON file ' + infofn )
return
return
info_dict [ ' __infojson_file path ' ] = infofn
info_dict [ ' __infojson_file name ' ] = infofn
thumbdir = os . path . dirname ( self . prepare_filepath ( filename , ' thumbnail ' ) )
thumbfn = self . prepare_filename ( info_dict , ' thumbnail ' )
for thumbfn in self . _write_thumbnails ( info_dict , temp_filename ) :
thumb_fn_temp = temp_filename if not skip_dl else thumbfn
files_to_move [ thumbfn ] = os . path . join ( thumbdir , os . path . basename ( thumbfn ) )
for thumb_ext in self . _write_thumbnails ( info_dict , thumb_fn_temp ) :
thumb_filename_temp = replace_extension ( thumb_fn_temp , thumb_ext , info_dict . get ( ' ext ' ) )
thumb_filename = replace_extension ( thumbfn , thumb_ext , info_dict . get ( ' ext ' ) )
files_to_move [ thumb_filename_temp ] = info_dict [ ' __thumbnail_filename ' ] = thumb_filename
# Write internet shortcut files
# Write internet shortcut files
url_link = webloc_link = desktop_link = False
url_link = webloc_link = desktop_link = False
@ -2247,7 +2257,7 @@ class YoutubeDL(object):
# Download
# Download
must_record_download_archive = False
must_record_download_archive = False
if not self . params. get ( ' skip_down load' , False ) :
if not skip_dl:
try :
try :
def existing_file ( * filepaths ) :
def existing_file ( * filepaths ) :
@ -2327,7 +2337,7 @@ class YoutubeDL(object):
new_info = dict ( info_dict )
new_info = dict ( info_dict )
new_info . update ( f )
new_info . update ( f )
fname = prepend_extension (
fname = prepend_extension (
self . prepare_file path( self . prepare_file name( new_info ) , ' temp ' ) ,
self . prepare_file name( new_info , ' temp ' ) ,
' f %s ' % f [ ' format_id ' ] , new_info [ ' ext ' ] )
' f %s ' % f [ ' format_id ' ] , new_info [ ' ext ' ] )
if not ensure_dir_exists ( fname ) :
if not ensure_dir_exists ( fname ) :
return
return
@ -2357,7 +2367,7 @@ class YoutubeDL(object):
self . report_error ( ' content too short (expected %s bytes and served %s ) ' % ( err . expected , err . downloaded ) )
self . report_error ( ' content too short (expected %s bytes and served %s ) ' % ( err . expected , err . downloaded ) )
return
return
if success and f ilename != ' - ' :
if success and f ull_f ilename != ' - ' :
# Fixup content
# Fixup content
fixup_policy = self . params . get ( ' fixup ' )
fixup_policy = self . params . get ( ' fixup ' )
if fixup_policy is None :
if fixup_policy is None :
@ -2439,7 +2449,7 @@ class YoutubeDL(object):
def download ( self , url_list ) :
def download ( self , url_list ) :
""" Download a given list of URLs. """
""" Download a given list of URLs. """
outtmpl = self . params. get ( ' outtmpl ' , DEFAULT_OUTTMPL )
outtmpl = self . outtmpl_dict[ ' default ' ]
if ( len ( url_list ) > 1
if ( len ( url_list ) > 1
and outtmpl != ' - '
and outtmpl != ' - '
and ' % ' not in outtmpl
and ' % ' not in outtmpl
@ -2522,12 +2532,13 @@ class YoutubeDL(object):
""" Run all the postprocessors on the given file. """
""" Run all the postprocessors on the given file. """
info = dict ( ie_info )
info = dict ( ie_info )
info [ ' filepath ' ] = filename
info [ ' filepath ' ] = filename
info [ ' __files_to_move ' ] = { }
for pp in ie_info . get ( ' __postprocessors ' , [ ] ) + self . _pps [ ' normal ' ] :
for pp in ie_info . get ( ' __postprocessors ' , [ ] ) + self . _pps [ ' normal ' ] :
files_to_move , info = self . run_pp ( pp , info , files_to_move )
files_to_move , info = self . run_pp ( pp , info , files_to_move )
info = self . run_pp ( MoveFilesAfterDownloadPP ( self , files_to_move ) , info , files_to_move )[ 1 ]
info = self . run_pp ( MoveFilesAfterDownloadPP ( self , files_to_move ) , info )[ 1 ]
for pp in self . _pps [ ' aftermove ' ] :
for pp in self . _pps [ ' aftermove ' ] :
files_to_move, info = self . run_pp ( pp , info , { } )
info = self . run_pp ( pp , info , { } ) [ 1 ]
def _make_archive_id ( self , info_dict ) :
def _make_archive_id ( self , info_dict ) :
video_id = info_dict . get ( ' id ' )
video_id = info_dict . get ( ' id ' )
@ -2878,7 +2889,7 @@ class YoutubeDL(object):
encoding = preferredencoding ( )
encoding = preferredencoding ( )
return encoding
return encoding
def _write_thumbnails ( self , info_dict , filename ) :
def _write_thumbnails ( self , info_dict , filename ) : # return the extensions
if self . params . get ( ' writethumbnail ' , False ) :
if self . params . get ( ' writethumbnail ' , False ) :
thumbnails = info_dict . get ( ' thumbnails ' )
thumbnails = info_dict . get ( ' thumbnails ' )
if thumbnails :
if thumbnails :
@ -2891,12 +2902,12 @@ class YoutubeDL(object):
ret = [ ]
ret = [ ]
for t in thumbnails :
for t in thumbnails :
thumb_ext = determine_ext ( t [ ' url ' ] , ' jpg ' )
thumb_ext = determine_ext ( t [ ' url ' ] , ' jpg ' )
suffix = ' _ %s ' % t [ ' id ' ] if len ( thumbnails ) > 1 else ' '
suffix = ' %s . ' % t [ ' id ' ] if len ( thumbnails ) > 1 else ' '
thumb_display_id = ' %s ' % t [ ' id ' ] if len ( thumbnails ) > 1 else ' '
thumb_display_id = ' %s ' % t [ ' id ' ] if len ( thumbnails ) > 1 else ' '
t [ ' filename ' ] = thumb_filename = replace_extension ( filename + suffix , thumb_ext , info_dict . get ( ' ext ' ) )
t [ ' filename ' ] = thumb_filename = replace_extension ( filename , suffix + thumb_ext , info_dict . get ( ' ext ' ) )
if not self . params . get ( ' overwrites ' , True ) and os . path . exists ( encodeFilename ( thumb_filename ) ) :
if not self . params . get ( ' overwrites ' , True ) and os . path . exists ( encodeFilename ( thumb_filename ) ) :
ret . append ( thumb_filename )
ret . append ( suffix + thumb_ext )
self . to_screen ( ' [ %s ] %s : Thumbnail %s is already present ' %
self . to_screen ( ' [ %s ] %s : Thumbnail %s is already present ' %
( info_dict [ ' extractor ' ] , info_dict [ ' id ' ] , thumb_display_id ) )
( info_dict [ ' extractor ' ] , info_dict [ ' id ' ] , thumb_display_id ) )
else :
else :
@ -2906,7 +2917,7 @@ class YoutubeDL(object):
uf = self . urlopen ( t [ ' url ' ] )
uf = self . urlopen ( t [ ' url ' ] )
with open ( encodeFilename ( thumb_filename ) , ' wb ' ) as thumbf :
with open ( encodeFilename ( thumb_filename ) , ' wb ' ) as thumbf :
shutil . copyfileobj ( uf , thumbf )
shutil . copyfileobj ( uf , thumbf )
ret . append ( thumb_filename )
ret . append ( suffix + thumb_ext )
self . to_screen ( ' [ %s ] %s : Writing thumbnail %s to: %s ' %
self . to_screen ( ' [ %s ] %s : Writing thumbnail %s to: %s ' %
( info_dict [ ' extractor ' ] , info_dict [ ' id ' ] , thumb_display_id , thumb_filename ) )
( info_dict [ ' extractor ' ] , info_dict [ ' id ' ] , thumb_display_id , thumb_filename ) )
except ( compat_urllib_error . URLError , compat_http_client . HTTPException , socket . error ) as err :
except ( compat_urllib_error . URLError , compat_http_client . HTTPException , socket . error ) as err :