I have a python (2.7) package which depends on a library written in C (The brain imaging suite Freesurfer). In order to check for the library I wrote the following:
def crash_if_freesurfer_not_found():
import os, subprocess
with open(os.devnull) as devnull:
p = subprocess.call(['which', 'mri_info'], stdout=devnull, stderr=devnull)
if p!=0:
print 'Useful error message'
sys.exit(1)
If which finds the program mri_info
in the path, then it has return code 0, otherwise it has return code 1. On the systems I developed this on, this worked.
I am on a system now, where this code is failing. But I was quite confused why, because `os.environ['PATH'] includes ~/freesurfer/bin, where this program is located.
In [3]: os.environ['PATH'].split(':')[0]
Out[3]: '/home/aestrivex/freesurfer/freesurfer/bin'
In [11]: ls /home/aestrivex/freesurfer/freesurfer/bin | grep mri_info
mri_info*
So I dug deeper and I found this odd behavior which I don't understand:
In [10]: with open(os.devnull) as nil:
p = subprocess.call(['which', 'mri_info'], stdout=nil, stderr=nil)
....:
In [11]: p
Out[11]: 1
In [12]: with open(os.devnull) as nil:
p = subprocess.call(['which', 'mri_info'], stdout=nil)
....:
sh: printf: I/O error
In [13]: with open(os.devnull) as nil:
p = subprocess.call(['which', 'mri_info'])
....:
/home/aestrivex/freesurfer/freesurfer/bin/mri_info
aestrivex@apocrypha ~/gselu $ which which
/usr/bin/which
So, which
fails with an I/O error whenever the python subprocess redirects stdout to /dev/null, and otherwise operates normally.
But I get perfectly normal behavior from which
otherwise than in a python subprocess
aestrivex@apocrypha ~/gselu $ which mri_info
/home/aestrivex/freesurfer/freesurfer/bin/mri_info
aestrivex@apocrypha ~/gselu $ which mri_info > /dev/null
aestrivex@apocrypha ~/gselu $ echo $?
0
There are several ways for me to fix this check, but my question is, what possible context could cause this bug to see which
behave like this in a python subprocess?