【发布时间】:2012-02-17 02:30:51
【问题描述】:
我正在编写一个包装器来通过 Python (2.7.2) 自动执行一些 android ADB shell 命令。 由于在某些情况下,我需要异步运行命令,因此我使用 subprocess.Popen 方法来发出 shell 命令。
我遇到了Popen 方法的[command, args] 参数的格式问题,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() 取得了相同的结果。
【问题讨论】:
-
您在问题中打错了字。 shlex 与 shelx。
-
@J.F.Sebastian 之前版本的(完整)代码实际上没有它就失败了。我现在改了
shell=False。谢谢你的评论。 -
不相关:
s.communicate()是一个阻塞调用,它等待进程终止(它不是异步的),因此您可以使用output = subprocess.check_output(args, stderr=STDOUT)而不是output = o.read()。 -
@J.F.Sebastian 我知道。这里的示例命令不是连续的,并且在进程终止之前有 s.communicate 阻塞是有意义的。异步情况将捕获
getevent或logcat的输出,直到从PC 客户端发出终止命令。 (严格来说,你不需要为 logcat 执行此操作,因为您可以读取日志文件,但您为 getevent 执行此操作。) -
s.split()和shlex.split(s)不相同!例如,尝试在 Python 控制台中比较以下内容:shlex.split('echo "foo bar is fun $(ls /tmp)"', posix=False)和'echo "foo bar is fun $(ls /tmp)"'.split()。经典的str.split()方法在逻辑上拆分字符串,但shlex.split(str)模块智能拆分字符串 - 正如 Shell 所理解的那样。
标签: python subprocess shlex