@@ -1024,7 +1024,7 @@ def _read(self, drain):
1024
1024
self ._lastidx = len (self ._rows )
1025
1025
1026
1026
1027
- def run_command (runtime , timeout = 0.01 ):
1027
+ def run_command (runtime , output = None , timeout = 0.01 ):
1028
1028
"""
1029
1029
Run a command, read stdout and stderr, prefix with timestamp. The returned
1030
1030
runtime contains a merged stdout+stderr log with timestamps
@@ -1038,50 +1038,81 @@ def run_command(runtime, timeout=0.01):
1038
1038
shell = True ,
1039
1039
cwd = runtime .cwd ,
1040
1040
env = runtime .environ )
1041
- streams = [
1042
- Stream ('stdout' , proc .stdout ),
1043
- Stream ('stderr' , proc .stderr )
1044
- ]
1041
+ result = {}
1042
+ if output == 'stream' :
1043
+ streams = [
1044
+ Stream ('stdout' , proc .stdout ),
1045
+ Stream ('stderr' , proc .stderr )
1046
+ ]
1045
1047
1046
- def _process (drain = 0 ):
1047
- try :
1048
- res = select .select (streams , [], [], timeout )
1049
- except select .error , e :
1050
- iflogger .info (str (e ))
1051
- if e [0 ] == errno .EINTR :
1052
- return
1048
+ def _process (drain = 0 ):
1049
+ try :
1050
+ res = select .select (streams , [], [], timeout )
1051
+ except select .error , e :
1052
+ iflogger .info (str (e ))
1053
+ if e [0 ] == errno .EINTR :
1054
+ return
1055
+ else :
1056
+ raise
1053
1057
else :
1054
- raise
1055
- else :
1056
- for stream in res [0 ]:
1057
- stream .read (drain )
1058
-
1059
- while proc .returncode is None :
1060
- proc .poll ()
1061
- _process ()
1062
- runtime .returncode = proc .returncode
1063
- _process (drain = 1 )
1064
-
1065
- # collect results, merge and return
1066
- result = {}
1067
- temp = []
1068
- for stream in streams :
1069
- rows = stream ._rows
1070
- temp += rows
1071
- result [stream ._name ] = [r [2 ] for r in rows ]
1072
- temp .sort ()
1073
- result ['merged' ] = [r [1 ] for r in temp ]
1058
+ for stream in res [0 ]:
1059
+ stream .read (drain )
1060
+
1061
+ while proc .returncode is None :
1062
+ proc .poll ()
1063
+ _process ()
1064
+ _process (drain = 1 )
1065
+
1066
+ # collect results, merge and return
1067
+ result = {}
1068
+ temp = []
1069
+ for stream in streams :
1070
+ rows = stream ._rows
1071
+ temp += rows
1072
+ result [stream ._name ] = [r [2 ] for r in rows ]
1073
+ temp .sort ()
1074
+ result ['merged' ] = [r [1 ] for r in temp ]
1075
+ if output == 'allatonce' :
1076
+ stdout , stderr = proc .communicate ()
1077
+ result ['stdout' ] = stdout .split ('\n ' )
1078
+ result ['stderr' ] = stderr .split ('\n ' )
1079
+ result ['merged' ] = ''
1080
+ if output == 'file' :
1081
+ errfile = os .path .join (runtime .cwd , 'stderr.nipype' )
1082
+ outfile = os .path .join (runtime .cwd , 'stdout.nipype' )
1083
+ stderr = open (errfile , 'wt' )
1084
+ stdout = open (outfile , 'wt' )
1085
+ proc = subprocess .Popen (runtime .cmdline ,
1086
+ stdout = stdout ,
1087
+ stderr = stderr ,
1088
+ shell = True ,
1089
+ cwd = runtime .cwd ,
1090
+ env = runtime .environ )
1091
+ ret_code = proc .wait ()
1092
+ stderr .flush ()
1093
+ stdout .flush ()
1094
+ result ['stdout' ] = [line .strip () for line in open (outfile ).readlines ()]
1095
+ result ['stderr' ] = [line .strip () for line in open (errfile ).readlines ()]
1096
+ result ['merged' ] = ''
1097
+ if output == 'none' :
1098
+ proc .communicate ()
1099
+ result ['stdout' ] = []
1100
+ result ['stderr' ] = []
1101
+ result ['merged' ] = ''
1074
1102
runtime .stderr = '\n ' .join (result ['stderr' ])
1075
1103
runtime .stdout = '\n ' .join (result ['stdout' ])
1076
1104
runtime .merged = result ['merged' ]
1105
+ runtime .returncode = proc .returncode
1077
1106
return runtime
1078
1107
1079
1108
1080
1109
class CommandLineInputSpec (BaseInterfaceInputSpec ):
1081
1110
args = traits .Str (argstr = '%s' , desc = 'Additional parameters to the command' )
1082
1111
environ = traits .DictStrStr (desc = 'Environment variables' , usedefault = True ,
1083
1112
nohash = True )
1084
-
1113
+ terminal_output = traits .Enum ('stream' , 'allatonce' , 'file' , 'none' ,
1114
+ desc = 'Control terminal output' , nohash = True ,
1115
+ mandatory = True )
1085
1116
1086
1117
class CommandLine (BaseInterface ):
1087
1118
"""Implements functionality to interact with command line programs
@@ -1117,6 +1148,7 @@ class must be instantiated with a command argument
1117
1148
input_spec = CommandLineInputSpec
1118
1149
_cmd = None
1119
1150
_version = None
1151
+ _terminal_output = 'stream'
1120
1152
1121
1153
def __init__ (self , command = None , ** inputs ):
1122
1154
super (CommandLine , self ).__init__ (** inputs )
@@ -1127,6 +1159,31 @@ def __init__(self, command=None, **inputs):
1127
1159
raise Exception ("Missing command" )
1128
1160
if command :
1129
1161
self ._cmd = command
1162
+ self .inputs .on_trait_change (self ._terminal_output_update ,
1163
+ 'terminal_output' )
1164
+ if not isdefined (self .inputs .terminal_output ):
1165
+ self .inputs .terminal_output = self ._terminal_output
1166
+ else :
1167
+ self ._output_update ()
1168
+
1169
+ def _terminal_output_update (self ):
1170
+ self ._terminal_output = self .inputs .terminal_output
1171
+
1172
+ @classmethod
1173
+ def set_default_terminal_output (cls , output_type ):
1174
+ """Set the default output type for FSL classes.
1175
+
1176
+ This method is used to set the default output type for all fSL
1177
+ subclasses. However, setting this will not update the output
1178
+ type for any existing instances. For these, assign the
1179
+ <instance>.inputs.output_type.
1180
+ """
1181
+
1182
+ if output_type in ['stream' , 'allatonce' , 'file' , 'none' ]:
1183
+ cls ._terminal_output = output_type
1184
+ else :
1185
+ raise AttributeError ('Invalid terminal output_type: %s' %
1186
+ output_type )
1130
1187
1131
1188
@property
1132
1189
def cmd (self ):
@@ -1207,7 +1264,7 @@ def _run_interface(self, runtime):
1207
1264
if not self ._exists_in_path (self .cmd .split ()[0 ]):
1208
1265
raise IOError ("%s could not be found on host %s" % (self .cmd .split ()[0 ],
1209
1266
runtime .hostname ))
1210
- runtime = run_command (runtime )
1267
+ runtime = run_command (runtime , output = self . inputs . terminal_output )
1211
1268
if runtime .returncode is None or runtime .returncode != 0 :
1212
1269
self .raise_exception (runtime )
1213
1270
0 commit comments