|
17 | 17 |
|
18 | 18 | from builtins import object, open, str, bytes
|
19 | 19 |
|
20 |
| -import gc |
21 | 20 | from copy import deepcopy
|
22 | 21 | from datetime import datetime as dt
|
23 |
| -import errno |
24 | 22 | import os
|
25 | 23 | import re
|
26 | 24 | import platform
|
27 |
| -import select |
28 | 25 | import subprocess as sp
|
29 | 26 | import shlex
|
30 | 27 | import sys
|
|
35 | 32 | from ... import config, logging, LooseVersion
|
36 | 33 | from ...utils.provenance import write_provenance
|
37 | 34 | from ...utils.misc import trim, str2bool, rgetcwd
|
38 |
| -from ...utils.filemanip import (FileNotFoundError, split_filename, read_stream, |
39 |
| - which, get_dependencies, canonicalize_env as |
40 |
| - _canonicalize_env) |
| 35 | +from ...utils.filemanip import (FileNotFoundError, split_filename, |
| 36 | + which, get_dependencies) |
| 37 | +from ...utils.subprocess import run_command |
41 | 38 |
|
42 | 39 | from ...external.due import due
|
43 | 40 |
|
44 | 41 | from .traits_extension import traits, isdefined, TraitError
|
45 | 42 | from .specs import (BaseInterfaceInputSpec, CommandLineInputSpec,
|
46 | 43 | StdOutCommandLineInputSpec, MpiCommandLineInputSpec)
|
47 |
| -from .support import (Bunch, Stream, InterfaceResult, NipypeInterfaceError) |
| 44 | +from .support import (Bunch, InterfaceResult, NipypeInterfaceError) |
48 | 45 |
|
49 | 46 | from future import standard_library
|
50 | 47 | standard_library.install_aliases()
|
@@ -732,135 +729,6 @@ def _list_outputs(self):
|
732 | 729 | return self._results
|
733 | 730 |
|
734 | 731 |
|
735 |
| -def run_command(runtime, output=None, timeout=0.01): |
736 |
| - """Run a command, read stdout and stderr, prefix with timestamp. |
737 |
| -
|
738 |
| - The returned runtime contains a merged stdout+stderr log with timestamps |
739 |
| - """ |
740 |
| - |
741 |
| - # Init variables |
742 |
| - cmdline = runtime.cmdline |
743 |
| - env = _canonicalize_env(runtime.environ) |
744 |
| - |
745 |
| - errfile = None |
746 |
| - outfile = None |
747 |
| - stdout = sp.PIPE |
748 |
| - stderr = sp.PIPE |
749 |
| - |
750 |
| - if output == 'file': |
751 |
| - outfile = os.path.join(runtime.cwd, 'output.nipype') |
752 |
| - stdout = open(outfile, 'wb') # t=='text'===default |
753 |
| - stderr = sp.STDOUT |
754 |
| - elif output == 'file_split': |
755 |
| - outfile = os.path.join(runtime.cwd, 'stdout.nipype') |
756 |
| - stdout = open(outfile, 'wb') |
757 |
| - errfile = os.path.join(runtime.cwd, 'stderr.nipype') |
758 |
| - stderr = open(errfile, 'wb') |
759 |
| - elif output == 'file_stdout': |
760 |
| - outfile = os.path.join(runtime.cwd, 'stdout.nipype') |
761 |
| - stdout = open(outfile, 'wb') |
762 |
| - elif output == 'file_stderr': |
763 |
| - errfile = os.path.join(runtime.cwd, 'stderr.nipype') |
764 |
| - stderr = open(errfile, 'wb') |
765 |
| - |
766 |
| - proc = sp.Popen( |
767 |
| - cmdline, |
768 |
| - stdout=stdout, |
769 |
| - stderr=stderr, |
770 |
| - shell=True, |
771 |
| - cwd=runtime.cwd, |
772 |
| - env=env, |
773 |
| - close_fds=(not sys.platform.startswith('win')), |
774 |
| - ) |
775 |
| - |
776 |
| - result = { |
777 |
| - 'stdout': [], |
778 |
| - 'stderr': [], |
779 |
| - 'merged': [], |
780 |
| - } |
781 |
| - |
782 |
| - if output == 'stream': |
783 |
| - streams = [ |
784 |
| - Stream('stdout', proc.stdout), |
785 |
| - Stream('stderr', proc.stderr) |
786 |
| - ] |
787 |
| - |
788 |
| - def _process(drain=0): |
789 |
| - try: |
790 |
| - res = select.select(streams, [], [], timeout) |
791 |
| - except select.error as e: |
792 |
| - iflogger.info(e) |
793 |
| - if e[0] == errno.EINTR: |
794 |
| - return |
795 |
| - else: |
796 |
| - raise |
797 |
| - else: |
798 |
| - for stream in res[0]: |
799 |
| - stream.read(drain) |
800 |
| - |
801 |
| - while proc.returncode is None: |
802 |
| - proc.poll() |
803 |
| - _process() |
804 |
| - |
805 |
| - _process(drain=1) |
806 |
| - |
807 |
| - # collect results, merge and return |
808 |
| - result = {} |
809 |
| - temp = [] |
810 |
| - for stream in streams: |
811 |
| - rows = stream._rows |
812 |
| - temp += rows |
813 |
| - result[stream._name] = [r[2] for r in rows] |
814 |
| - temp.sort() |
815 |
| - result['merged'] = [r[1] for r in temp] |
816 |
| - |
817 |
| - if output.startswith('file'): |
818 |
| - proc.wait() |
819 |
| - if outfile is not None: |
820 |
| - stdout.flush() |
821 |
| - stdout.close() |
822 |
| - with open(outfile, 'rb') as ofh: |
823 |
| - stdoutstr = ofh.read() |
824 |
| - result['stdout'] = read_stream(stdoutstr, logger=iflogger) |
825 |
| - del stdoutstr |
826 |
| - |
827 |
| - if errfile is not None: |
828 |
| - stderr.flush() |
829 |
| - stderr.close() |
830 |
| - with open(errfile, 'rb') as efh: |
831 |
| - stderrstr = efh.read() |
832 |
| - result['stderr'] = read_stream(stderrstr, logger=iflogger) |
833 |
| - del stderrstr |
834 |
| - |
835 |
| - if output == 'file': |
836 |
| - result['merged'] = result['stdout'] |
837 |
| - result['stdout'] = [] |
838 |
| - else: |
839 |
| - stdout, stderr = proc.communicate() |
840 |
| - if output == 'allatonce': # Discard stdout and stderr otherwise |
841 |
| - result['stdout'] = read_stream(stdout, logger=iflogger) |
842 |
| - result['stderr'] = read_stream(stderr, logger=iflogger) |
843 |
| - |
844 |
| - runtime.returncode = proc.returncode |
845 |
| - try: |
846 |
| - proc.terminate() # Ensure we are done |
847 |
| - except OSError as error: |
848 |
| - # Python 2 raises when the process is already gone |
849 |
| - if error.errno != errno.ESRCH: |
850 |
| - raise |
851 |
| - |
852 |
| - # Dereference & force GC for a cleanup |
853 |
| - del proc |
854 |
| - del stdout |
855 |
| - del stderr |
856 |
| - gc.collect() |
857 |
| - |
858 |
| - runtime.stderr = '\n'.join(result['stderr']) |
859 |
| - runtime.stdout = '\n'.join(result['stdout']) |
860 |
| - runtime.merged = '\n'.join(result['merged']) |
861 |
| - return runtime |
862 |
| - |
863 |
| - |
864 | 732 | class CommandLine(BaseInterface):
|
865 | 733 | """Implements functionality to interact with command line programs
|
866 | 734 | class must be instantiated with a command argument
|
|
0 commit comments