Python 子进程命令未使用ls命令查找文件?
我正在创建一个程序,它将拉入一个帐号列表,然后运行Python 子进程命令未使用ls命令查找文件?,python,subprocess,python-2.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}.zi
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)
下面是我通过Python解释器运行命令时的一些示例输出:
>>>ls:无法访问*CSV1000*应用程序*:没有此类文件或目录
但通过Linux,同样的命令:
ls-lh*CSV*应用程序*
这是因为shell使用与模式匹配的现有文件替换通配符。例如,如果您有
a.txt
和b.txt
,则ls*.txt
将从shell扩展到ls a.txt b.txt
。使用您的命令,您实际上要求ls
返回有关文件名中包含星号的文件的信息。如果要验证,请使用以下命令:
sp.Popen(['bash', '-c', 'ls', '-lh', '*CSV*APP*{0}.zip'.format(e)])
您还应该使用
os.chdir
来更改目录,因为sp.call(['cd',input_dir])
会更改您创建的新进程的当前目录,而不是父进程的当前目录。我认为您需要将shell=True
作为参数添加到Popen中,并用一个字符串替换列表:
proc_out = sp.Popen('ls -lh *CSV*APP*{0}.zip'.format(e), shell=True)
请参见此处,了解更多信息以及glob
的可能用法:您应该使用and,然后才能获得输出
您的代码如下所示:
import subprocess as sp
for i, e in enumerate(piv_id_list):
proc = sp.Popen(['ls', '-lh', '*CSV*APP*{0}.zip'.format(e)], cwd=input_dir, stdout=sp.PIPE, shell=True)
proc_out_list.append(proc.communicate()[0])
print(proc_out_list[-1])
但是为什么要创建子流程而不是使用标准库呢
您希望使用
子流程
模块处理无法(轻松)在纯Python中实现的事情(即:使用ffmpeg
编码视频,使用passwd
更改用户passowrd,使用sudo
升级权限,…)。ls
,通过Python运行,可能是对的:我想当前目录中没有名为*CSV*APP*
的文件。可能有一个文件的名称与该glob模式匹配。但是ls
并不关心globs。在shell上运行该命令时会发生的情况是,shell将glob扩展到它可以在当前目录中看到的匹配文件名,这些扩展的名称就是shell传递给ls的文件名
要在shell中获得与Python中相同的结果(用于演示,不是因为您希望这样),请通过单引号保护参数不受glob扩展的影响:
ls-lh'*CVS*APP*'${e}.zip'
但是如何在Python中获得shell的行为呢?您可以像其他一些答案所建议的那样使用shell=True
,但这是一个滑铁卢,因为在动态生成的字符串上调用实际的shell(可能取决于更复杂的应用程序中的用户输入)会使您容易受到命令注入和其他肮脏行为的攻击
在这里,您只需要shell的一个特定行为,filename globbing。Python恰好能够做到这一点:
正如所示,这仍然会出现在错误的目录中,因为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)
注
您可能可以使用而不是直接使用。我认为子流程是操作系统模块的替代品?
子流程
只取代了os
的一小部分,即os.popen()
及其直系族(popen2
,popen3
,等等)。请参阅,例如,我是否应该只安装操作系统模块以了解所有信息?看起来简单多了,因为我可以像在Linux中一样,以字符串的形式输入命令。这就是我要做的。您不会有任何像ls
这样的外部依赖项,它可以在其他操作系统上工作,并且没有那么困难……如果可以的话,我会的,不幸的是,我们正在运行第2.6版:/@flybonzai:1。传递cwd
参数而不是os.chdir()
的全局性更小(更好)。2.这很容易理解。3.您根本不需要调用ls
:您可以使用glob
模块获取文件名和os.path.getsize()
获取文件大小,或者使用os.stat()
获取您可能需要的任何其他信息。
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)