convert: catch OSErrors and display error message

This also adds close_fds (only available on Unixes) to the common subprocess
invocation utility.
This commit is contained in:
Adrian Sampson 2014-04-03 19:47:21 -07:00
parent ac99622ec7
commit d407db725f
3 changed files with 16 additions and 20 deletions

View file

@ -23,6 +23,7 @@ import fnmatch
from collections import defaultdict
import traceback
import subprocess
import platform
MAX_FILENAME_LENGTH = 200
WINDOWS_MAGIC_PREFIX = u'\\\\?\\'
@ -594,8 +595,9 @@ def command_output(cmd):
Python 2.6 and which can have problems if lots of output is sent to
stderr.
"""
with open(os.devnull, 'w') as devnull:
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=devnull)
with open(os.devnull, 'wb') as devnull:
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=devnull,
close_fds=platform.system() != 'Windows')
stdout, _ = proc.communicate()
if proc.returncode:
raise subprocess.CalledProcessError(proc.returncode, cmd)

View file

@ -17,11 +17,10 @@
import logging
import os
import threading
from subprocess import Popen
import subprocess
import tempfile
from string import Template
import pipes
import platform
from beets.plugins import BeetsPlugin
from beets import ui, util
@ -39,19 +38,6 @@ ALIASES = {
}
def _silent_popen(args):
"""Invoke a command (like subprocess.Popen) while silencing its
error output. Return the Popen object.
"""
# On Windows, close_fds doesn't work (i.e., raises an exception)
# when stderr is redirected.
return Popen(
args,
close_fds=platform.system() != 'Windows',
stderr=open(os.devnull, 'wb'),
)
def _destination(dest_dir, item, keep_new, path_formats):
"""Return the path under `dest_dir` where the file should be placed
(possibly after conversion).
@ -113,10 +99,11 @@ def encode(source, dest):
log.debug(u'convert: executing: {0}'.format(
u' '.join(pipes.quote(o.decode('utf8', 'ignore')) for o in opts)
))
encode = _silent_popen(opts)
encode.wait()
if encode.returncode != 0:
try:
util.command_output(opts)
except subprocess.CalledProcessError:
# Something went wrong (probably Ctrl+C), remove temporary files
log.info(u'Encoding {0} failed. Cleaning up...'
.format(util.displayable_path(source)))
@ -124,6 +111,11 @@ def encode(source, dest):
util.prune_dirs(os.path.dirname(dest))
return
except OSError as exc:
raise ui.UserError(
u'convert: could invoke ffmpeg: {0}'.format(exc)
)
if not quiet:
log.info(u'Finished encoding {0}'.format(
util.displayable_path(source))

View file

@ -69,6 +69,8 @@ Fixes:
* :doc:`/plugins/importfeeds`: Fix crash when importing albums
containing ``/`` with the ``m3u_multi`` format.
* Avoid crashing on Mutagen bugs while writing files' tags.
* :doc:`/plugins/convert`: Display a useful error message when the FFmpeg
executable can't be found.
.. _requests: http://www.python-requests.org/