7

我正在编写一个包装器来通过 Python(2.7.2)自动化一些 android ADB shell 命令。因为在某些情况下,我需要异步运行命令,所以我使用subprocess .Popen方法来发出 shell 命令。

我遇到了方法[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()取得相同的结果。

4

2 回答 2

5

shell=True参数告诉它让您的 shell 评估命令行,在 Windows 上将为Cmd.exe; 在 Linux 上,它可能是/bin/bash,但也可能是其他一些相关的 shell(zsh、tcsh 等)。行为上的差异可能是由 shell 以不同方式解释命令引起的。

如果可以避免,我强烈建议不要使用它。shell=True就像这样:

cmd = 'adb -s <serialnumber> shell ls /system'
s = subprocess.Popen(cmd.split())  # shell=False by default
于 2012-02-17T02:49:01.653 回答
5

当我关闭它们时,它们的功能似乎相同shell=True

根据文档:

在 Unix 上,shell=True:如果 args 是一个字符串,它指定要通过 shell 执行的命令字符串。这意味着字符串的格式必须与在 shell 提示符下键入时的格式完全相同。这包括,例如,引用或反斜杠转义文件名,其中包含空格。如果 args 是一个序列,则第一项指定命令字符串,任何附加项都将被视为 shell 本身的附加参数。也就是说,Popen 相当于:

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

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

于 2012-02-17T02:51:12.293 回答