当前位置:  开发笔记 > 编程语言 > 正文

如何逃避os.system()调用?

如何解决《如何逃避os.system()调用?》经验,为你挑选了5个好方法。

使用os.system()时,通常需要将作为参数传递的文件名和其他参数转义为命令.我怎样才能做到这一点?优选地,可以在多个操作系统/壳上工作但特别是用于bash的东西.

我目前正在做以下操作,但我确定必须有一个库函数,或者至少是一个更优雅/更健壮/更有效的选项:

def sh_escape(s):
   return s.replace("(","\\(").replace(")","\\)").replace(" ","\\ ")

os.system("cat %s | grep something | sort > %s" 
          % (sh_escape(in_filename), 
             sh_escape(out_filename)))

编辑:我接受了使用引号的简单答案,不知道为什么我没有想到这一点; 我猜是因为我来自Windows,其中'和'的表现略有不同.

关于安全性,我理解这个问题,但是,在这种情况下,我对os.system()提供的快速简单的解决方案感兴趣,并且字符串的来源要么不是用户生成的,要么至少是由用户输入的.可信用户(我).



1> pixelbeat..:

shlex.quote() 从python 3开始你想做什么.

(pipes.quote用于支持python 2和python 3)


更正:在3.3中正式记录为[`shlex.quote()`](http://docs.python.org/dev/py3k/library/shlex.html#shlex.quote),`pipes.quote()`保留兼容性.[http://bugs.python.org/issue9723]
管道在Windows上不起作用 - 添加双引号的单引号.
由于某种原因,管道模块的标准库文档没有提到`pipes.quote`(http://docs.python.org/library/pipes.html)

2> Greg Hewgill..:

这是我使用的:

def shellquote(s):
    return "'" + s.replace("'", "'\\''") + "'"

shell将始终接受带引号的文件名,并在将其传递给相关程序之前删除周围的引号.值得注意的是,这避免了包含空格或任何其他令人讨厌的shell元字符的文件名的问题.

更新:如果您使用的是Python 3.3或更高版本,请使用shlex.quote而不是自己滚动.


请注意,除非您绝对需要shell功能,否则您应该使用Jamie的建议.
@pixelbeat:这就是为什么他关闭他的单引号,添加一个转义的文字单引号,然后再次重新打开他的单引号.
类似于此的内容现在正式以[shlex.quote](http://docs.python.org/dev/library/shlex.html#shlex.quote)的形式提供.
虽然这不是shellquote函数的责任,但可能有趣的是,如果在此函数的返回值之前出现一个不带引号的反斜杠,这仍然会失败.士气:确保您在可信赖的代码中使用此代码(例如硬编码命令的一部分) - 不要将其附加到其他未加引号的用户输入.
这个答案提供的功能比`shlex`或`pipes`更好地引用了shell。这些python模块错误地认为特殊字符是唯一需要引号的内容,这意味着当不希望出现这种行为时,将解析shell关键字(如time,case或while)。出于这个原因,我建议在此答案中使用单引号例程,因为它不会尝试变得“聪明”,所以不会出现那些愚蠢的情况。

3> Jamie..:

也许你有特定的使用理由os.system().但如果没有,你可能应该使用该subprocess模块.您可以直接指定管道并避免使用shell.

以下内容来自PEP324:

Replacing shell pipe line
-------------------------

output=`dmesg | grep hda`
==>
p1 = Popen(["dmesg"], stdout=PIPE)
p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
output = p2.communicate()[0]


`subprocess`(特别是`check_call`等)通常非常优越,但是有一些情况下shell转义仍然有用.我遇到的主要问题是当我不得不调用ssh远程命令时.

4> Gary Shi..:

也许subprocess.list2cmdline是一个更好的镜头?


它没有正确地逃脱\:`subprocess.list2cmdline(["'",'',"\\",'"'])`给''""\"

5> John Wiseman..:

请注意,pipes.quote实际上在Python 2.5和Python 3.1中已损坏,并且不安全使用-它不处理零长度参数。

>>> from pipes import quote
>>> args = ['arg1', '', 'arg3']
>>> print 'mycommand %s' % (' '.join(quote(arg) for arg in args))
mycommand arg1  arg3

参见Python问题7476 ; 它已在Python 2.6和3.2及更高版本中修复。


您正在使用哪个版本的Python?2.6版似乎产生了正确的输出:mycommand arg1''arg3(这是两个单引号,尽管Stack Overflow上的字体很难分辨!)
推荐阅读
手机用户2502852037
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有