54

我有一个试图使用 Python 解析的文件目录。如果它们都是相同的扩展名,我不会有问题,但无论出于何种原因,它们都是在原始扩展名之后使用顺序数字扩展名创建的。例如:foo.log foo.log.1 foo.log.2 bar.log bar.log.1 bar.log.2 etc.最重要的是,foo.log 是 XML 格式,而 bar.log 不是。为了只读取和解析foo.log.* and foo.log文件,最好的方法是什么?这些bar.log文件不需要读取。下面是我的代码:

import os
from lxml import etree
path = 'C:/foo/bar//'
listing = os.listdir(path)
for files in listing:
    if files.endswith('.log'):
        print files
        data = open(os.path.join(path, files), 'rb').read()
        tree = etree.fromstring(data)
        search = tree.findall('.//QueueEntry')

这不起作用,因为它不读取任何.log.*文件,并且解析器阻塞了已读取但不是 xml 格式的文件。谢谢!

4

4 回答 4

113

也许glob模块可以帮助你:

import glob

listing = glob.glob('C:/foo/bar/foo.log*')
for filename in listing:
    # do stuff
于 2012-11-08T20:49:46.337 回答
16

为了只读取和解析foo.log.*andfoo.log文件,最好的方法是什么?bar.log 文件不需要读取。

您的代码执行此操作:

if files.endswith('.log'):

您刚刚将您的英文描述翻译成 Python 有点错误。你用 Python 写的是:“只读取和解析*.log文件”,意思bar.log是包含,foo.log.1不包含。

但如果你想一想,你可以将你的英文描述直接翻译成 Python:

if files == 'foo.log' or files.startswith('foo.log.'):

如果您考虑一下,只要没有foo.log.您想要跳过的名为(带有那个额外点)的文件,您就可以将这两种情况合并为一种:

if files.startswith('foo.log'):

但是,如果您对 POSIX shell 有所了解,则foo.log*匹配完全相同的东西。(这对于 Windows shell 来说不是这样,通配符专门处理扩展名,这就是为什么你必须键入*.*而不是*.)并且 Python 带有一个模块,即使在 Windows 上也可以执行 POSIX 样式的通配符,称为glob. 有关如何使用它的信息,请参阅 stranac 的答案。

我认为glob答案比手动过滤要好listdir。它更简单,它更直接地匹配您的问题标题所说的您想要做的事情(只需完全按照您希望使用的方式进行操作os.listdir,但glob.glob改为使用),并且更灵活。因此,除非您担心通配符的两种略有不同的含义会混淆,否则我建议您接受它而不是这个。

于 2012-11-08T23:52:33.937 回答
7

这将为您提供类似 bash 的正则表达式:

import glob
print(glob.glob("/tmp/o*"))

或者,您可以 os.listdir 整个目录,并通过 re 模块丢弃与正则表达式不匹配的文件。

于 2012-11-08T20:50:23.703 回答
0

正如一些已经提到的:您可以使用 glob.glob 使用通配符查找文件。我不能写评论,这是一个非常古老的问题,但是......有人建议,glob.glob 不能在路径中扩展〜。因此,您可以使用 os.path.expanduser 来扩展环境变量。

于 2021-03-06T10:43:13.063 回答