|
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