diff --git a/docs/configuration.rst b/docs/configuration.rst index 36a0f4be..88dd060e 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -3808,6 +3808,42 @@ Description * ``{3}`` is percent of bytes downloaded to total bytes +output.stdout & .stdin & .stderr +-------------------------------- +Type + * ``string`` + * ``object`` +Example + .. code:: json + + "utf-8" + + .. code:: json + + { + "encoding": "utf-8", + "errors": "replace", + "line_buffering": true + } + +Description + `Reconfigure `__ + a `standard stream `__. + + Possible options are + + * ``encoding`` + * ``errors`` + * ``newline`` + * ``line_buffering`` + * ``write_through`` + + When this option is specified as a simple ``string``, + it is interpreted as ``{"encoding": "", "errors": "replace"}`` + + Note: ``errors`` always defaults to ``"replace"`` + + output.shorten -------------- Type diff --git a/gallery_dl/__init__.py b/gallery_dl/__init__.py index 3d3dbad0..ca9a767b 100644 --- a/gallery_dl/__init__.py +++ b/gallery_dl/__init__.py @@ -33,9 +33,6 @@ def progress(urls, pformat): def main(): try: - if sys.stdout and sys.stdout.encoding.lower() != "utf-8": - output.replace_std_streams() - parser = option.build_parser() args = parser.parse_args() log = output.initialize_logging(args.loglevel) @@ -77,6 +74,8 @@ def main(): for opts in args.options: config.set(*opts) + output.configure_standard_streams() + # signals signals = config.get((), "signals-ignore") if signals: diff --git a/gallery_dl/output.py b/gallery_dl/output.py index 8905b021..7d74b699 100644 --- a/gallery_dl/output.py +++ b/gallery_dl/output.py @@ -271,16 +271,32 @@ else: stderr_write = stderr_write_flush -def replace_std_streams(errors="replace"): - """Replace standard streams and set their error handlers to 'errors'""" - for name in ("stdout", "stdin", "stderr"): - stream = getattr(sys, name) - if stream: +def configure_standard_streams(): + for name in ("stdout", "stderr", "stdin"): + options = config.get(("output",), name) + if not options: + continue + + stream = getattr(sys, name, None) + if not stream: + continue + + if isinstance(options, str): + options = {"encoding": options, "errors": "replace"} + elif not options.get("errors"): + options["errors"] = "replace" + + try: + stream.reconfigure(**options) + except AttributeError: + # no 'reconfigure' support + oget = options.get setattr(sys, name, stream.__class__( stream.buffer, - errors=errors, - newline=stream.newlines, - line_buffering=stream.line_buffering, + encoding=oget("encoding", stream.encoding), + errors=oget("errors", "replace"), + newline=oget("newline", stream.newlines), + line_buffering=oget("line_buffering", stream.line_buffering), ))