fly*_*zai 6 python subprocess python-2.6
我正在创建一个程序,它将提取一个帐号列表,然后运行一个ls -lh命令来查找每个帐号.当我在没有Python的Linux服务器上运行我的命令时,它会提取文件没问题,但是当我通过Python执行它时它说它无法找到它们.
import subprocess as sp
sp.call(['cd', input_dir])
for i, e in enumerate(piv_id_list):
proc_out = sp.Popen(['ls', '-lh', '*CSV*APP*{0}.zip'.format(e)])
proc_out_list.append(proc_out)
print(proc_out)
Run Code Online (Sandbox Code Playgroud)
这是通过Python解释器运行命令时的一些示例输出:
>>> ls:无法访问*CSV1000*APP*:没有这样的文件或目录
但是通过Linux同样的命令:
ls -lh *CSV*APP*
Run Code Online (Sandbox Code Playgroud)
它会像它应该的那样返回输出.
这是因为shell使用与模式匹配的现有文件替换通配符.例如,如果你有a.txt和b.txt,然后ls *.txt将从外壳扩展ls a.txt b.txt.使用您的命令,您实际上要求ls返回有关其文件名中包含星号的文件的信息.如果要验证,请使用以下内容:
sp.Popen(['bash', '-c', 'ls', '-lh', '*CSV*APP*{0}.zip'.format(e)])
Run Code Online (Sandbox Code Playgroud)
您还应该使用os.chdir更改目录,因为sp.call(['cd', input_dir])更改了您创建的新进程的当前目录,而不是父目录.
ls通过 Python 运行时,可能是正确的:我猜当前目录中没有调用任何文件。*CSV*APP*可能存在一个名称与该全局模式匹配的文件。但ls不关心全局。当您在 shell 上运行该命令时,会发生什么情况:shell 将 glob 扩展为它可以在当前目录中看到的匹配文件名,并且这些扩展名称是 shell 传递给ls.
要在 shell 中获得与 Python 中相同的结果(用于演示,而不是因为您想要这样),请使用单引号保护参数免遭全局扩展:
ls -lh '*CVS*APP*'${e}'.zip'
Run Code Online (Sandbox Code Playgroud)
但是如何在 Python 中获得 shell 的行为呢?您可以使用shell=True,但这是一个滑坡,因为在动态生成的字符串上调用实际的 shell(可能取决于更复杂的应用程序中的用户输入)可能会使您容易受到命令注入和其他恶意行为的影响。
在这里,您只需要shell 的一种特定行为,即文件名匹配。Python 恰好能够自己完成这一切:
import subprocess as sp
from glob import glob
sp.call(['cd', input_dir])
for i, e in enumerate(piv_id_list):
proc_out = sp.Popen(['ls', '-lh', glob('*CSV*APP*{0}.zip'.format(e))])
proc_out_list.append(proc_out)
print(proc_out)
Run Code Online (Sandbox Code Playgroud)
正如JuniorCompressor 所指出的,这仍然会在错误的目录中查找,因为这cd只会影响调用的子进程,所以cd让我们也修复这个问题:
import subprocess as sp
from glob import glob
os.chdir(input_dir)
for i, e in enumerate(piv_id_list):
proc_out = sp.Popen(['ls', '-lh', glob('*CSV*APP*{0}.zip'.format(e))])
proc_out_list.append(proc_out)
print(proc_out)
Run Code Online (Sandbox Code Playgroud)
笔记
您可能可以直接使用稍高级别的sp.check_output层而不是底层sp.Popen。
| 归档时间: |
|
| 查看次数: |
1116 次 |
| 最近记录: |