Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/311.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 子进程命令未使用ls命令查找文件?_Python_Subprocess_Python 2.6 - Fatal编程技术网

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])
但是为什么要创建子流程而不是使用标准库呢

编辑 正如@tripleee所说,它只替换了一些功能。 我认为在可能的情况下最好使用内置/stdlib;在本例中,您“只”希望列出给定模式()的文件,并显示有关其大小的有序()信息()

使用stdlib使您的代码更易于移植;即使您不关心Microsoft Windows的可移植性,您也可能希望避免在没有GNU binutils(即Mac OS、BSD等)的计算机上运行代码时遇到意外


您希望使用
子流程
模块处理无法(轻松)在纯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)