/usr/bin/在作为python子进程调用时具有奇怪的行为

2024-04-20 12:05:54 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个python(2.7)包,它依赖于用C(brain imaging suite Freesurfer)编写的库。为了检查库,我写了以下内容:

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)

如果在路径中找到程序mri_info,则返回代码为0,否则返回代码为1。在我开发的系统上,这是有效的。你知道吗

我现在在一个系统上,这个代码失败了。但我很困惑为什么,因为`操作系统环境['PATH']包括~/freesurfer/bin,此程序位于此位置。你知道吗

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*

所以我深入挖掘,发现了一个奇怪的行为,我不明白:

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

因此,每当python子进程将stdout重定向到/dev/null时,which就会失败并出现I/O错误,否则就会正常运行。你知道吗

但是我从which得到了完全正常的行为,而不是在python子进程中

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

有几种方法可以修复这个检查,但我的问题是,什么可能的上下文会导致这个bug在python子进程中看到which这样的行为?你知道吗


Tags: ininfowhichbinosaswithopen