subprocess.Popen()管道问题

时间:2017-03-12 14:26:34

标签: python linux subprocess popen

关于先前部分解决的问题(Python issue running subprocess.Popen() from a .py in console)。我仍然发现一些我无法解决的错误。

代码的重要部分如下:

proc = subprocess.Popen(['/bin/bash','-c', '-i', 'which conda'], stdout=subprocess.PIPE)
conda_location = proc.stdout.read().decode('ascii')
conda_location = conda_location[:-1]
print('ANACONDA LOCATION: ', conda_location)

#some stuff

print('Checking presence of HOMER files...')
proc = subprocess.Popen(['/bin/bash', '-c', '-i', 'which findMotifs.pl'], stdout=subprocess.PIPE)
p = proc.stdout.read().decode('ascii')
p = p[:-1]

#more stuff

如果我在PyCharm IDE控制台中运行此代码,它运行没有任何问题。但是,如果我在Linux终端中运行它,会发生以下情况:

现在,如果我切换进程,第二个进程(现在是第一个进程)运行,第一个进程(现在是第二个进程)停止。此外,如果我独立运行每个进程,它们工作正常。

这一发现让我觉得第一个进程可能正在等待,第二个进程被停止。但是,当我运行proc.wait()proc.kill()proc.terminate()时,没有任何操作会使第二个功能正常工作,并且仍会停止。

我还尝试添加.communicate()shell=True,但无济于事。

提前谢谢

1 个答案:

答案 0 :(得分:0)

这不是一个Python问题,而是一个bash问题。

给bash -i(交互式)标志告诉bash它是交互式的,即它应该从stdin读取输入并执行输入的任何命令。 (当然,首先它运行你给它的-c命令 - 但之后 ....)

Bash的stdin与Python的stdin相同,因为你没有重定向它。所以bash试图从stdin读取。本身,这不会那么糟糕 - 但bash也会作业控制,这意味着它必须接管进程,进程组等的分配,以确保只有一个管道prog1 | prog2 | prog3一次可以从终端读取。因此,Bash试图从Python会话中夺取对终端的控制权,其中外部 shell将控制权传递给该Python会话。

结果是SIGTTINSIGTTOUSIGTSTP信号(从一个操作系统到另一个操作系统的细节各不相同;看起来Linux给了你一个SIGTSTP但是我的BSD实验得到了一个{ {1}};请参阅http://curiousthing.org/sigttin-sigttou-deep-dive-linux了解更多相关信息)和一般不良行为,因为各种流程都会争夺谁可​​以做什么,什么时候,什么时候会议。

最简单的治疗方法与您之前所说的相同:放下SIGTTIN标志。

如果-i 找不到的情况下使程序可以查找,则表示您的环境配置不正确,例如,仅在-i中设置PATH即使~/.bashrc不是您的主要内容(如果您的主要内容为bash,则PATH设置应位于~/.profile中。