Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
Next release
============

* ENH: Allows controlling how commandline interface terminal output is handled.

Release 0.7.0 (Dec 18, 2012)
============================
Expand Down
8 changes: 8 additions & 0 deletions doc/users/config_file.rst
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,14 @@ Execution
version information is available. Please notify developers or submit a
patch.

*commandline_output (CommandLine interfaces only)*
Controls how terminal output from a command line is handled. There are 4
possible options. (default: 'stream' for current compatibility)
`stream`: line by line streaming to terminal
`allatonce`: streams after command has terminated
`file`: writes output to stdout.nipype and stderr.nipype
`none`: suppresses all output

Example
~~~~~~~

Expand Down
94 changes: 64 additions & 30 deletions nipype/interfaces/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -1038,42 +1038,76 @@ def run_command(runtime, timeout=0.01):
shell=True,
cwd=runtime.cwd,
env=runtime.environ)
streams = [
Stream('stdout', proc.stdout),
Stream('stderr', proc.stderr)
]
result = {}
if config.get('execution', 'commandline_output').lower() == 'stream':
streams = [
Stream('stdout', proc.stdout),
Stream('stderr', proc.stderr)
]

def _process(drain=0):
try:
res = select.select(streams, [], [], timeout)
except select.error, e:
iflogger.info(str(e))
if e[0] == errno.EINTR:
return
def _process(drain=0):
try:
res = select.select(streams, [], [], timeout)
except select.error, e:
iflogger.info(str(e))
if e[0] == errno.EINTR:
return
else:
raise
else:
raise
else:
for stream in res[0]:
stream.read(drain)

while proc.returncode is None:
proc.poll()
_process()
runtime.returncode = proc.returncode
_process(drain=1)
for stream in res[0]:
stream.read(drain)

while proc.returncode is None:
proc.poll()
_process()
runtime.returncode = proc.returncode
_process(drain=1)

# collect results, merge and return
temp = []
for stream in streams:
rows = stream._rows
temp += rows
result[stream._name] = [r[2] for r in rows]
temp.sort()
result['merged'] = [r[1] for r in temp]
elif config.get('execution', 'commandline_output').lower() == 'allatonce':
stdout, stderr = proc.communicate()
result['stdout'] = stdout.split('\n')
result['stderr'] = stderr.split('\n')
result['merged'] = ''
elif config.get('execution', 'commandline_output').lower() == 'file':
errfile = os.path.join(runtime.cwd, 'stderr.nipype')
outfile = os.path.join(runtime.cwd, 'stdout.nipype')
stderr = open(errfile, 'wt')
stdout = open(outfile, 'wt')
proc = subprocess.Popen(runtime.cmdline,
stdout=stdout,
stderr=stderr,
shell=True,
cwd=runtime.cwd,
env=runtime.environ)
ret_code = proc.wait()
stderr.flush()
stdout.flush()
result['stdout'] = [line.strip() for line in open(outfile).readlines()]
result['stderr'] = [line.strip() for line in open(errfile).readlines()]
result['merged'] = ''
elif config.get('execution', 'commandline_output').lower() == 'none':
proc.communicate()
result['stdout'] = []
result['stderr'] = []
result['merged'] = ''
else:
raise ValueError(("Unknown input for config['execution']"
"['commandline_output']. Should be one of 'stream', "
"'allatonce', 'file', or 'none'"))

# collect results, merge and return
result = {}
temp = []
for stream in streams:
rows = stream._rows
temp += rows
result[stream._name] = [r[2] for r in rows]
temp.sort()
result['merged'] = [r[1] for r in temp]
runtime.stderr = '\n'.join(result['stderr'])
runtime.stdout = '\n'.join(result['stdout'])
runtime.merged = result['merged']
runtime.returncode = proc.returncode
return runtime


Expand Down
33 changes: 33 additions & 0 deletions nipype/interfaces/tests/test_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -461,3 +461,36 @@ def test_Commandline_environ():
ci3.inputs.environ = {'DISPLAY' : ':2'}
res = ci3.run()
yield assert_equal, res.runtime.environ['DISPLAY'], ':2'


def test_CommandLine_output():
from nipype import config
config.set_default_config()
config.set('execution', 'commandline_output', 'foo')
ci = nib.CommandLine(command='ls -l')
yield assert_raises, ValueError, ci.run

tmp_infile = setup_file()
tmpd, name = os.path.split(tmp_infile)
pwd = os.getcwd()
os.chdir(tmpd)
yield assert_true, os.path.exists(tmp_infile)
config.set('execution', 'commandline_output', 'allatonce')
ci = nib.CommandLine(command='ls -l')
res = ci.run()
yield assert_equal, res.runtime.merged, ''
yield assert_true, name in res.runtime.stdout
config.set('execution', 'commandline_output', 'file')
ci = nib.CommandLine(command='ls -l')
res = ci.run()
yield assert_true, 'stdout.nipype' in res.runtime.stdout
config.set('execution', 'commandline_output', 'none')
ci = nib.CommandLine(command='ls -l')
res = ci.run()
yield assert_equal, res.runtime.stdout, ''
config.set('execution', 'commandline_output', 'stream')
ci = nib.CommandLine(command='ls -l')
res = ci.run()
yield assert_true, 'stdout.nipype' in res.runtime.stdout
os.chdir(pwd)
teardown_file(tmpd)
3 changes: 2 additions & 1 deletion nipype/pipeline/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -670,7 +670,8 @@ def clean_working_directory(outputs, cwd, inputs, needed_outputs, config,
input_files.extend(walk_outputs(inputdict))
needed_files += [path for path, type in input_files if type == 'f']
for extra in ['_0x*.json', 'provenance.xml', 'pyscript*.m',
'command.txt', 'result*.pklz', '_inputs.pklz', '_node.pklz']:
'command.txt', 'result*.pklz', '_inputs.pklz', '_node.pklz',
'stderr.nipype', 'stdout.nipype']:
needed_files.extend(glob(os.path.join(cwd, extra)))
if files2keep:
needed_files.extend(filename_to_list(files2keep))
Expand Down
1 change: 1 addition & 0 deletions nipype/utils/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
stop_on_first_rerun = false
use_relative_paths = false
stop_on_unknown_version = false
commandline_output = stream

[check]
interval = 1209600
Expand Down