Python的子进程不像cygwin那样解释“〜”

时间:2013-11-21 17:40:06

标签: python bash shell cygwin subprocess

第17.1.1.1节。 documentation个州:

  

如果shell为True,则将通过shell执行指定的命令。如果您主要使用Python来提供它在大多数系统shell上提供的增强控制流,并且仍然希望方便地访问其他shell功能,例如shell管道,文件名通配符,环境变量扩展以及将〜扩展到用户家中,这将非常有用。 。目录

但是,在 cygwin 上, bash 的输出与 Python的子进程的输出不同,即:

击:

$ ls -ls ~rbarakx
total 0
0 drwxr-xr-x 1 Administrator None 0 Aug 21 17:54 bash
0 drwxr-xr-x 1 Administrator None 0 Jul 11 09:11 python

的Python:

>>> subprocess.call(["ls","-ls","~rbarakx"],shell=True)
RCS  mecha.py  print_unicode.py  req.py  requests_results.html  selen.py
0

看起来 subprocess.call 正在执行 ls

你能说明原因吗?

我的环境:
Python :Python 2.7.3(默认,2012年12月18日,13:50:09)[GCC 4.5.3] on cygwin
cygwin :CYGWIN_NT-6.1-WOW64 ... 1.7.22(0.268 / 5/3)... i686 Cygwin
windows :Windows 7旗舰版

3 个答案:

答案 0 :(得分:4)

在Windows上,shell(cmd.exe)不支持将~扩展到用户的主目录。就此而言,也不是通配符扩展。在这一点上,Python文档非常面向UNIX / Linux。

“但是等等!”我听到你哭了。 “我安装了cygwin,我有bash!”当然有,但你几乎不能指望Python知道这一点。你在Windows上,所以它将使用Windows shell。如果没有,那么期望shell为cmd.exe的Python脚本将会非常困惑。

答案 1 :(得分:3)

有趣的是,当将命令作为字符串而不是元组传递时,它似乎就像在bash中执行它一样。

subprocess.call(["ls -ls ~"], shell=True)

如果您坚持使用元组,请考虑以下解决方法:

cmd = subprocess.list2cmdline(["ls","-ls","~rbarakx"])
subprocess.call(cmd, shell=True)

或者这个:

from os.path import expanduser
subprocess.call(["ls","-ls", expanduser("~rbarakx")])

答案 2 :(得分:3)

  

看起来subprocess.call正在执行ls。

     

你能说明原因吗?

因为在Unix(cygwin)上你的电话相当于:

# WRONG: DON'T DO IT
rc = subprocess.call(["/bin/sh", "-c"] + ["ls","-ls","~rbarakx"])

换句话说,参数列表会传递给shell本身,即ls看不到-ls~rbarakx它们被认为是/bin/sh个参数。

你想要的是:

rc = subprocess.call(["/bin/sh", "-c"] + ["ls -ls ~rbarakx"])

或使用shell=True

rc = subprocess.call("ls -ls ~rbarakx", shell=True)

以下是subprocess docs for reference的引用:

  

在Unix上 shell=True,shell默认为/bin/sh。如果args是   string,string指定通过shell执行的命令。   这意味着字符串必须完全按照原样进行格式化   在shell提示符下键入时。这包括,例如,引用或   反斜杠转义文件名,其中包含空格。 如果args是   sequence,第一项指定命令字符串,以及任何   其他项目将被视为shell的附加参数   也就是说,Popen相当于:

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

强调是我的

您也可以在没有任何shell的情况下执行命令:

import os
import subprocess

rc = subprocess.call(["ls", "-ls", os.path.expanduser("~rbarakx")])
相关问题