|
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