|
19 | 19 | import abc
|
20 | 20 | import base64
|
21 | 21 | import contextlib
|
22 |
| -from io import BytesIO |
| 22 | +from io import BytesIO, TextIOWrapper |
23 | 23 | import itertools
|
24 | 24 | import logging
|
25 | 25 | import os
|
@@ -346,12 +346,11 @@ def _run(self):
|
346 | 346 | # movie file. *args* returns the sequence of command line arguments
|
347 | 347 | # from a few configuration options.
|
348 | 348 | command = self._args()
|
349 |
| - output = subprocess.PIPE |
350 | 349 | _log.info('MovieWriter.run: running command: %s', command)
|
351 |
| - self._proc = subprocess.Popen(command, shell=False, |
352 |
| - stdout=output, stderr=output, |
353 |
| - stdin=subprocess.PIPE, |
354 |
| - creationflags=subprocess_creation_flags) |
| 350 | + PIPE = subprocess.PIPE |
| 351 | + self._proc = subprocess.Popen( |
| 352 | + command, stdin=PIPE, stdout=PIPE, stderr=PIPE, |
| 353 | + creationflags=subprocess_creation_flags) |
355 | 354 |
|
356 | 355 | def finish(self):
|
357 | 356 | '''Finish any processing for writing the movie.'''
|
@@ -394,8 +393,18 @@ def cleanup(self):
|
394 | 393 | '''Clean-up and collect the process used to write the movie file.'''
|
395 | 394 | out, err = self._proc.communicate()
|
396 | 395 | self._frame_sink().close()
|
397 |
| - _log.debug('MovieWriter -- Command stdout:\n%s', out) |
398 |
| - _log.debug('MovieWriter -- Command stderr:\n%s', err) |
| 396 | + # Use the encoding/errors that universal_newlines would use. |
| 397 | + out = TextIOWrapper(BytesIO(out)).read() |
| 398 | + err = TextIOWrapper(BytesIO(err)).read() |
| 399 | + _log.debug("MovieWriter stdout:\n%s", out) |
| 400 | + _log.debug("MovieWriter stderr:\n%s", err) |
| 401 | + if self._proc.returncode: |
| 402 | + raise RuntimeError('Error creating movie, return code {}\n' |
| 403 | + 'stdout:\n' |
| 404 | + '{}\n' |
| 405 | + 'stderr:\n' |
| 406 | + '{}\n' |
| 407 | + .format(self._proc.returncode, out, err)) |
399 | 408 |
|
400 | 409 | @classmethod
|
401 | 410 | def bin_path(cls):
|
@@ -520,19 +529,6 @@ def finish(self):
|
520 | 529 | self._run()
|
521 | 530 | MovieWriter.finish(self) # Will call clean-up
|
522 | 531 |
|
523 |
| - # Check error code for creating file here, since we just run |
524 |
| - # the process here, rather than having an open pipe. |
525 |
| - if self._proc.returncode: |
526 |
| - try: |
527 |
| - stdout = [s.decode() for s in self._proc._stdout_buff] |
528 |
| - stderr = [s.decode() for s in self._proc._stderr_buff] |
529 |
| - _log.info("MovieWriter.finish: stdout: %s", stdout) |
530 |
| - _log.info("MovieWriter.finish: stderr: %s", stderr) |
531 |
| - except Exception as e: |
532 |
| - pass |
533 |
| - raise RuntimeError('Error creating movie, return code: {}' |
534 |
| - .format(self._proc.returncode)) |
535 |
| - |
536 | 532 | def cleanup(self):
|
537 | 533 | MovieWriter.cleanup(self)
|
538 | 534 |
|
@@ -894,17 +890,7 @@ def grab_frame(self, **savefig_kwargs):
|
894 | 890 | else:
|
895 | 891 | return super().grab_frame(**savefig_kwargs)
|
896 | 892 |
|
897 |
| - def _run(self): |
898 |
| - # make a duck-typed subprocess stand in |
899 |
| - # this is called by the MovieWriter base class, but not used here. |
900 |
| - class ProcessStandin(object): |
901 |
| - returncode = 0 |
902 |
| - |
903 |
| - def communicate(self): |
904 |
| - return '', '' |
905 |
| - |
906 |
| - self._proc = ProcessStandin() |
907 |
| - |
| 893 | + def finish(self): |
908 | 894 | # save the frames to an html file
|
909 | 895 | if self.embed_frames:
|
910 | 896 | fill_frames = _embedded_frames(self._saved_frames,
|
|
0 commit comments