subprocess通配符使用
问题原因:在使用subprocess模块的通配符时,可能会遇到以下问题:
1. 当设置shell=True
时,需要确保路径没有被引号括起来,否则shell无法进行扩展。
2. 如果路径中包含特殊字符,需要手动进行转义。
解决方法:
1. 确保路径没有被引号括起来,或者可以尝试将shell=True
设置为False,来避免shell扩展路径。
2. 如果路径中包含特殊字符,可以手动进行转义,以确保正确的匹配和处理。
示例代码:
import subprocess # 1. 确保路径没有被引号括起来,或设置shell=False path_without_quotes = "/path/to/file/*.txt" subprocess.run(["ls", path_without_quotes], shell=False) # 2. 手动转义特殊字符 path_with_special_chars = "/path/with/special/characters/*.txt" escaped_path = "/path/with/special/characters/\*.txt" subprocess.run(["ls", escaped_path], shell=True)
问题的原因是在使用subprocess模块执行命令时,如果需要通过shell解释器执行命令,则需要将shell参数设置为True。然而,这样做的话,就不能再将命令作为列表的第一个参数进行传递,因为参数会被加上引号。相反,需要将原始的命令行作为参数传递给shell。
解决方法是使用以下方式来执行命令:
proc = subprocess.Popen('ls *.bc', shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
这样可以正常执行命令。有些在互联网上找到的示例之所以将命令作为列表的第一个参数,通常是因为不希望shell解释参数。想象一下,如果将用户输入作为命令的一部分,比如`'ls ' + user_supplied_path`,用户可以输入`'; shutdown -s'`作为路径,这样系统就会停止运行。而使用`['ls', user_supplied_path]`的方式可以防止这种注入攻击。
在动态情况下,这种注入攻击可能非常危险,比如`Popen("ls " + filename, shell=True)`,其中filename等于`blahblah; rm -rf /`。可以参考这个链接了解更多信息。
为了避免这种问题,可以考虑使用`subprocess.run()`等替代`Popen()`的方法。可以参考这个链接了解更多信息。
问题的原因是,默认情况下,subprocess模块不会通过shell发送命令,因此命令中的通配符*会被作为一个字面量参数使用,而不会被shell进行展开。这样做的好处是可以避免安全问题和一些编程错误。
解决方法是使用glob模块来替代shell进行通配符展开。通过import glob导入模块,并使用glob.glob()函数来获取匹配通配符的文件列表。
这种方法更快、更可靠,并且跨平台(不依赖于平台是否有ls命令)。
subprocess模块不会通过shell发送命令的原因是为了避免安全问题和编程错误。相关的文档已经明确说明了shell=True的含义,并且默认情况下是shell=False。
使用glob模块可以得到一个可操作的Python对象,更加符合Python编程的习惯。
参考链接:
- subprocess文档中的"常用参数"章节的警告部分:https://docs.python.org/2.7/library/subprocess.html#frequently-used-arguments
- glob模块文档:http://docs.python.org/library/glob.html
- subprocess文档中关于shell参数的说明:https://stackoverflow.com/questions/3172470