Python子进程输出到列表或文件

9
我希望在Python 3中执行以下bash命令:
ls -l

我知道我可以做以下操作:

from subprocess import call
call(['ls', '-l'])

如何将此输出保存到文件中,或将其放入列表或集合中?

[-rw-r--r--]  [1] [name]  [staff]   [426] [14 Jan 21:52] [HelloWorld.class]
[-rw-r--r--@] [1] [name]  [staff]   [107] [14 Jan 21:51] [HelloWorld.java]
...
etc.

我希望能够直接访问特定的信息并将其添加到集合中,但是我不知道会列出多少项。

任何提示、片段或示例都会非常有帮助。


1
如果您想访问文件/目录信息,您可能需要检查内置的 os 库:文档 - Rik Poggi
6个回答

28
使用>= python3.5,您可以使用subprocess.run
ls_lines = subprocess.run(['ls', '-l'], stdout=subprocess.PIPE).stdout.splitlines()

使用>= python2.7或>= python3.0,您可以使用subprocess.check_output
ls_lines = subprocess.check_output(['ls', '-l']).splitlines()

在Python2.7之前,你需要使用较低级别的API,这需要更多的操作。
ls_proc = subprocess.Popen(['ls', '-l'], stdout=subprocess.PIPE)
ls_proc.wait()
# check return code
ls_lines = ls_proc.stdout.readlines()

subprocess.PIPE* - undefined

14

解析ls -l输出中的信息的一种方法是进行解析。例如,可以使用csv.DictReader将每一列映射到字典中的一个字段:

import subprocess
import csv

process = subprocess.Popen(['ls', '-l'], stdout=subprocess.PIPE)
stdout, stderr = process.communicate()

reader = csv.DictReader(stdout.decode('ascii').splitlines(),
                        delimiter=' ', skipinitialspace=True,
                        fieldnames=['permissions', 'links',
                                    'owner', 'group', 'size',
                                    'date', 'time', 'name'])

for row in reader:
    print(row)

上面的代码将为ls -l输出中的每一行打印一个字典,例如:

{'group': '<group_name>',
 'name': '<filename>',
 'links': '1',
 'date': '<modified_date>',
 'time': '<modified_time>',
 'owner': '<user_name>',
 'permissions': '-rw-rw-r--',
 'size': '<size>'}

我得到了以下错误信息:File "ip4.py", line 16 print row ^ SyntaxError: invalid syntax - beoliver
@user969617 是的,抱歉,那是针对Python 2.x的,而不是你所要求的Python 3。我已经更新了代码以适用于Python 3。 - jcollado
这看起来很有前途!!!我的下一个问题(请忍耐,这是我学习 Python 的第二天)是如何访问每个字典中的信息。我需要给它们唯一的名称吗?假设我想将日期与电子表格进行交叉引用。 - beoliver
@user969617 不需要给字典命名。你可以将它们存储在一个列表中,通过索引访问列表,并通过键访问字典:rows[0]['name'] - jcollado
谢谢,你的代码完美地解析了hadoop fs -ls也没问题!!!!! - Bohdan

7

如果你真正想要列出一个目录,最好使用os.listdir

import os
files = os.listdir('/path/to/dir')
for file in files:
    print(file)

我实际上想要列出机场表,但是认为我会使用一个简单的例子。实际输出将是call(['/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport', '-s']) - beoliver

2

阅读关于Popen的内容。您所要求的设置可以使用以下方式获得:

import subprocess
proc = subprocess.Popen(['ls','-l'],stdout=subprocess.PIPE,stderr=subprocess.PIPE)
myset=set(proc.stdout)

或者像这样做
for x in proc.stdout : print x

同样适用于stderr

您可以使用以下命令查看进程状态

proc.poll() 

或者等待它使用

终止

proc.wait()

也可以阅读

逐行读取子进程的标准输出


0

已经有人回应了。不过,以防万一有人需要

import subprocess
output_list=subprocess.check_output(['locate','*.nse']).decode('utf-8').split('\n')[:-1]

0
from subprocess import Popen, PIPE
output = Popen(['ls', '-l'], stdout=PIPE).communicate()[0]

你可以随意处理输出结果。有关详细文档,请参见python docs


谢谢。我也尝试过这个,但是由于缺乏格式化,我感到有些困惑... 我通常使用bash和awk来处理事情,其中打印输出然后使用awk '{print $n;}'可以让你进入列,而awk NR=$variable则可以让你选择行。我应该看哪个部分? - beoliver
@Gary 指出了一种在Python2.7+中实现的不错的方法。如果可以的话,请使用它 :) - Wesley

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接