将变量传递给子流程

时间:2019-01-25 04:31:07

标签: python bash subprocess ipython

我想知道如何将python变量传递给subprocess.check_output命令。

在这种情况下,我有lowerupper python变量要传递给subprocess.check_output命令,但是我确定我在下面的操作方式是不正确的因为它没有给我预期的结果。

如果我手动输入下限值和上限值,则它确实可以工作。

 for qq in range (0, 5, 1): 
      lo = glob.glob(path2 + "IM" + path1 + "*_GM.nii.gz")  
      lo = ' '.join(lo)
      lower = qq - 0.5
      upper = qq + 0.5
      subprocess.check_output(['fslstats {} -l lower -u upper -V | cut -d " " -f 1'.format(lo)], shell=True)

有人建议我如何传递上下变量?

注意:

lo= /Users/say/Documents/awIM/network5/awfc_GM.nii.gz

path2=/Users/say/Documents/aw

path1=/network5/awfc

谢谢

1 个答案:

答案 0 :(得分:1)

已发布社区Wiki,因为此一个已经在知识库中其他位置提出并回答的问题。


正确执行此操作(但为了支持本机Python字符串操作而删除了cut)可能类似于:

glob_str = path2 + "IM" + path1 + "*_GM.nii.gz"
glob_list = glob.glob(glob_str)
if len(glob_list) == 0:
    raise Exception("No results found from glob expression %r" % glob_str)
for qq in range (0, 5, 1):
    lower = qq - 0.5
    upper = qq + 0.5
    args = ['fslstats'] + glob_list + [ '-l', str(lower), '-u', str(upper), '-V' ]
    ### EVERYTHING BELOW HERE IS UNNECESSARILY COMPLICATED BY THE USE OF 'cut'
    ### CONSIDER REPLACING WITH THE ALTERNATE IMPLEMENTATION  BELOW.
    p1 = subprocess.Popen(args, stdout=subprocess.PIPE)
    p1.stdout.close()
    p2 = subprocess.Popen(['cut', '-d', ' ', '-f1'], stdin=p1.stdout)
    (stdout, _) = p2.communicate()
    if p1.wait() != 0:
      raise Exception("fslstats run as %r returned exit status %r" % (args, p1.returncode))
    print("Result is: %r" % (stdout.split("\n"),))

要删除cut,您可以按以下方式更改分配args的行下方的所有内容:

    stdout = subprocess.check_output(args)
    first_column = [ line.split()[0] for line in stdout.split('\n') ]
    print("Result is: %r" % first_column)

注意:

  • 我们不使用shell=True禁用此功能可以实现您拥有更多控制权的实现-外壳不会在后面做任何事情,而您不会不需要知道该外壳如何工作以及如何实现以避免(可能影响安全的)错误。
  • 要实现不包含shell=True的管道,我们将遵循https://docs.python.org/2/library/subprocess.html#replacing-shell-pipeline中记录的做法
  • 我们实际上是在传递lowerupper变量的值,而不是传递命令lowerupper字符串。
  • 我们没有将我们的glob结果连接到一个字符串中(如果由该glob产生的任何文件名包含空格,这都会破坏我们的命令),而是直接将该列表传递到fslstats的参数列表中。 / li>
  • 因为您关心的是fslstats而不是cut的退出状态,所以需要检查一下自己。 (即使使用shell=True,您也会获得默认的Shell行为,该行为仅返回最后一个管道组件的退出状态。)