Назначение экземпляров в os.walk в python - PullRequest
0 голосов
/ 13 декабря 2011

Я пытаюсь создать Уокер, который просматривает каталоги. Вот входы и выходы, над которыми я частично работаю. Я использую тестовый каталог, но я хотел бы, чтобы это было сделано в любом каталоге, который приводит к некоторым проблемам.

[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

Есть ли способ добавить другие сложные функции в DirLister от Anurag ниже? Поэтому, когда он попадает в файл с именем 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

Просто нужно знать, как включить его в класс ниже. Спасибо.

Ответы [ 2 ]

1 голос
/ 13 декабря 2011

Я предполагаю, что вы хотите, чтобы 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, мы предполагаем, что пользователь пытается получить доступ к этому каталогу под данным корнем, поэтому мы создаем еще один DirLister с корнем root+subdirname

def __getattr__(self, name):
    try:
        var = super(DirLister).__getattr__(self, name)
        return var
    except AttributeError:
        return DirLister(os.path.join(self.root, name))

Примечание: сначала мы проверяем базовый класс на предмет этого атрибута, потому что мы не хотим рассматривать доступ ко всем переменным как доступ к подчиненному каталогу, если такого атрибута, следовательно, нет AttributeError, то мы создаем новый DirLister для подпапки .

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']
0 голосов
/ 13 декабря 2011

Не уверен, что вы спрашиваете, но сработает ли это?

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']
...