передача переменной в подпроцесс - PullRequest
0 голосов
/ 25 января 2019

Мне было интересно, как я могу передать переменную python в команду subprocess.check_output.

В данном конкретном случае у меня есть переменные lower и upper для 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 голосов
/ 25 января 2019

Опубликовано вики сообщества, потому что - это вопрос, который уже задан и дан ответ в другом месте базы знаний.


Делаем это правильно (но для удаленияcut в пользу манипуляции со строкой собственного Python) может выглядеть примерно так:

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
  • На самом деле мы передаем значения переменных lower и upper вместо передачи строк lower и upper.
  • Мы не присоединяемся к нашемуglob приводит к появлению строки (которая разбивала бы нашу команду, если в именах файлов, содержащихся в этом глобусе, содержались пробелы), но вместо этого передавал список непосредственно в списке аргументов для fslstats.
  • , так как вы заботитесь о выходестатус fslstats, а не cut, вы должны проверить это самостоятельно.(Даже с shell=True вы получаете поведение оболочки по умолчанию, которое возвращает только состояние завершения последнего конвейерного компонента).
...