我正在尝试创建一个遍历目录的walker。以下是我部分工作的输入和输出。我正在使用测试目录,但我希望在任何导致某些问题的目录上完成此操作。
[IN]: print testdir #name of the directory
[OUT]: ['j','k','l'] #directories under testdir
[IN]: print testdir.j
[OUT]: ['m','n'] # Files under testdir.j
以下是目前的代码:
class directory_lister:
"""Lists directories under root"""
def __init__(self,path):
self.path = path
self.ex = []
for item in os.listdir(path):
self.ex.append(item)
def __repr__(self):
return repr(self.ex)
这将返回目录和文件,但我必须手动分配目录的名称。
testdir = directory_lister(path/to/testdir)
j = directory_lister(path/to/j)
etc
有没有办法自动化实例:
for root,dirs,files in os.walk(/path/to/testdir/):
for x in dirs:
x = directory_lister(root) #I want j = directory_lister(path/to/j), k = directory_lister(path/to/k) and l = directory_lister(path/to/l) here.
可以有:
class directory_lister:
def __init__(self,path):
self.path = path
self.j = directory_lister(path + os.sep + j) # how to automate this attribute of the class when assigned to an instance??
上面的代码是错误的,因为对象x只是一个实例,但必须手动定义j,k,l。我是否必须使用 getattr 的其他类或字典,但我总是遇到同样的问题。如果需要任何额外信息,请询问,我希望我明白这一点。
更新2
有没有办法通过下面的Anurag将其他复杂功能添加到DirLister?所以当它到达一个文件时说testdir / j / p时,会打印出文件p的第一行。
[IN] print testdir.j.p
[OUT] First Line of p
我已经创建了一个用于打印文件第一行的类:
class File:
def __init__(self, path):
"""Read the first line in desired path"""
self.path = path
f = open(path, 'r')
self.first_line = f.readline()
f.close()
def __repr__(self):
"""Display the first line"""
return self.first_line
只需要知道如何将它合并到下面的课程中。谢谢。
答案 0 :(得分:1)
我假设您希望sub-dir可以像属性一样访问,您可以实现这两种方式
我更喜欢第二种方法,因为它更懒惰,更好,更容易实现
import os
class DirLister(object):
def __init__(self, root):
self.root = root
self._list = None
def __getattr__(self, name):
try:
var = super(DirLister).__getattr__(self, name)
return var
except AttributeError:
return DirLister(os.path.join(self.root, name))
def __str__(self):
self._load()
return str(self._list)
def _load(self):
"""
load once when needed
"""
if self._list is not None:
return
self._list = os.listdir(self.root) # list root someway
root = DirLister("/")
print root.etc.apache2
输出:
['mods-enabled', 'sites-80', 'mods-available', 'ports.conf', 'envvars', 'httpd.conf', 'sites-available', 'conf.d', 'magic', 'apache2.conf', 'sites-enabled']
您可以对此进行改进,以便更好地进行错误检查等
代码说明:这基本上是目录的递归列表,因此DirLister
个对象列出给定根目录下的文件,如果用虚线表示法访问某个变量,则返回DirLister假设该属性是根目录下的文件夹。因此,如果我们尝试逐步创建DirLister
类,则会更清楚
1-一个简单的DirLister
,只列出其下的文件/文件夹
class DirLister(object):
def __init__(self, root):
self.root = root
self._list = os.listdir(self.root)
2-我们的简单列表文件只列出一个级别的文件,如果我们想要在子文件夹下获取文件管理器,我们可以挂钩到使用__getattr__
时使用varname调用的obj.varname
。因此,如果我们的dir-lister没有名为varname的属性,我们假设用户正在尝试访问给定root下的该目录,因此我们创建另一个根目录为root+subdirname
的DirLister
def __getattr__(self, name):
try:
var = super(DirLister).__getattr__(self, name)
return var
except AttributeError:
return DirLister(os.path.join(self.root, name))
注意:首先我们检查该属性的基类,因为我们不希望将所有变量访问视为子目录访问,如果没有这样的属性因此AttributeError
那么我们为sub创建一个新的DirLister -folder。
3-要改进代码以便我们不列出所有文件夹,即使用户没有要求它们,我们也只会在用户需要时列出,因此load
方法
def _load(self):
if self._list is not None:
return
self._list = os.listdir(self.root) # list root someway
所以这个方法列出了dir(如果尚未列出的话),当我们最终需要它时应该调用它,例如打印列表时
编辑:正如OP所要求的那样是递归列出整棵树的替代方法,虽然我强烈建议反对它
import os
class RecursiveDirLister(object):
def __init__(self, root):
self._sublist = []
for folder in os.listdir(root):
self._sublist.append(folder)
path = os.path.join(root, folder)
if not os.path.isdir(path):
continue
# add it as attribute, assuming that dir-name is valid python varname
try:
sublister = RecursiveDirLister(path)
except OSError:
continue#ignore permission errors etc
setattr(self, folder, sublister)
def __str__(self):
return str(self._sublist)
etc = RecursiveDirLister("/etc")
print etc.fonts
输出:
['conf.avail', 'conf.d', 'fonts.conf', 'fonts.dtd']
答案 1 :(得分:0)
不确定你在问什么,但这会有用吗?
for root,dirs,files in os.walk(/path/to/testdir/):
listers = dict((dir, directory_lister(dir)) for dir in dirs)
#now you can use:
listers['j']
listers['k']
listers['l']