Почему subprocess.Popen не работает, когда args является последовательностью?
У меня проблема с subprocess.Popen, когда параметр args задан как последовательность.
Например:
import subprocess
maildir = "/home/support/Maildir"
Это работает (печатает правильный размер /home/support/Maildir dir):
size = subprocess.Popen(["du -s -b " + maildir], shell=True,
stdout=subprocess.PIPE).communicate()[0].split()[0]
print size
Но это не работает (попробуйте):
size = subprocess.Popen(["du", "-s -b", maildir], shell=True,
stdout=subprocess.PIPE).communicate()[0].split()[0]
print size
В чем дело?
3 ответа
Из документации
В Unix с shell=True: […] Если args является последовательностью, первый элемент задает командную строку, и любые дополнительные элементы будут рассматриваться как дополнительные аргументы самой оболочки. То есть Попен делает эквивалент:
Popen(['/bin/sh', '-c', args[0], args[1], ...])
Что в вашем случае означает:
Popen(['/bin/sh', '-c', 'du', '-s', '-b', maildir])
Это означает, что -s
, -b
а также maildir
интерпретируются как параметры оболочкой, а не du
(попробуйте это в командной строке оболочки!).
поскольку shell=True
в любом случае вам не нужно, вы можете просто удалить его:
size = subprocess.Popen(['du', '-s', '-b', maildir],
stdout=subprocess.PIPE).communicate()[0].split()[0]
В качестве альтернативы вы можете просто использовать свой оригинальный подход, но в этом случае вам не нужен список. Вы также должны позаботиться о пробелах в имени каталога:
size = subprocess.Popen('du -s -b "%s"' % maildir, shell=True,
stdout=subprocess.PIPE).communicate()[0].split()[0]
Из документа,
В Unix с shell = True: если args является строкой, она указывает командную строку для выполнения через оболочку. Если args - последовательность, первый элемент задает командную строку, и любые дополнительные элементы будут рассматриваться как дополнительные аргументы оболочки.
Так что постарайтесь
subprocess.Popen("du -s -b " + maildir, ...
или же
subprocess.Popen(["du","-s","-b",maildir], ...