subprocess.Popen и shlex.split форматирование в Windows и Linux - PullRequest
6 голосов
/ 17 февраля 2012

Я пишу оболочку для автоматизации некоторых команд оболочки Android ADB через Python (2.7.2).Поскольку в некоторых случаях мне нужно выполнить команду асинхронно, я использую метод subprocess .Popen для выдачи команд оболочки.

Я столкнулся с проблемой с форматированиемПараметр [command, args] метода Popen, где требуется разделение команды / аргументов, отличается в Windows и Linux:

# sample command with parameters
cmd = 'adb -s <serialnumber> shell ls /system'

# Windows:
s = subprocess.Popen(cmd.split(), shell=False) # command is split into args by spaces

# Linux:
s = subprocess.Popen([cmd], shell=False) # command is a list of length 1 containing whole command as single string

Я пытался использовать shlex .split (),с и без флага posix:

# Windows
posix = False
print shlex.split(cmd, posix = posix), posix
# Linux
posix = True
print shlex.split(cmd, posix = posix), posix

Оба случая возвращают одинаковое разделение.

Есть ли в subprocess или shlex метод, который обрабатывает специфичные для ОС форматы правильно ?

Это мое текущее решение:

import os
import tempfile
import subprocess
import shlex

# determine OS type
posix = False
if os.name == 'posix':
    posix = True

cmd = 'adb -s <serialnumber> shell ls /system'
if posix: # posix case, single command string including arguments
    args = [cmd]
else: # windows case, split arguments by spaces
    args = shlex.split(cmd)

# capture output to a temp file
o = tempfile.TemporaryFile()
s = subprocess.Popen(args, shell=False, stdout=o, stderr=o)
s.communicate()
o.seek(0)
o.read()
o.close()

Я не думаю, что shlex.split() здесь что-то делает, и cmd.split() достигает идентичных результатов.

Ответы [ 2 ]

5 голосов
/ 17 февраля 2012

Кажется, что они работают одинаково, когда я выключаю shell=True

Согласно документации:

В Unix с shell = True: если args - строка, этоуказывает командную строку для выполнения через оболочку.Это означает, что строка должна быть отформатирована точно так же, как при вводе в командной строке.Это включает, например, кавычки или обратную косую черту, экранирующие имена файлов с пробелами в них.Если args - последовательность, первый элемент задает командную строку, и любые дополнительные элементы будут обрабатываться как дополнительные аргументы самой оболочки.То есть Popen делает эквивалент:

Popen (['/ bin / sh', '-c', args [0], args [1], ...])

http://docs.python.org/library/subprocess.html

4 голосов
/ 17 февраля 2012

Аргумент shell=True указывает, что ваша оболочка должна оценивать командную строку, которая в Windows будет Cmd.exe;в Linux это, вероятно, будет /bin/bash, но также может быть и другая связанная оболочка (zsh, tcsh и т. д.).Разница в поведении, вероятно, вызвана тем, что оболочки по-разному интерпретируют команды.

Я бы настоятельно рекомендовал , а не , используя shell=True, если вы можете избежать этого.Просто как то так:

cmd = 'adb -s <serialnumber> shell ls /system'
s = subprocess.Popen(cmd.split())  # shell=False by default
...