2014-01-03 4 views
2

Я пытаюсь удалить несколько файлов в каталоге.Удалить файлы с разными именами в Python

До сих пор у меня есть этот код:

for filename in glob.glob("buffer*"): 
     os.remove(filename) 
    for filename in glob.glob("grid*"): 
     os.remove(filename) 
    for filename in glob.glob("OSMroads*"): 
     os.remove(filename) 
    for filename in glob.glob("newCostSurface*"): 
     os.remove(filename) 
    for filename in glob.glob("standsLine*"): 
     os.remove(filename) 
    for filename in glob.glob("standsReprojected*"): 
     os.remove(filename) 

Есть ли способ сделать это более эффективным?

+0

Какие файлы вы пытаетесь удалить? Это самый простой способ сгруппировать их? Каковы их имена? Нам нужна дополнительная информация. –

+0

Что вы подразумеваете под "более эффективным"? Более эффективно для людей читать/обновлять/поддерживать свой код? Более эффективен для работы компьютера? Или что-то другое? – abarnert

+0

Я имею в виду оба: более эффективный для чтения и более эффективный, поэтому мой код выполняется быстрее. – ustroetz

ответ

4

Doing 6 отдельных glob вызовы, конечно, итерацию объект каталога 6 раз.

К счастью, практически на любой платформе он, вероятно, в конечном итоге будет кэширован после первого раза. Если ваш каталог не является абсолютно гигантским, это не будет заметной проблемой.

Но так как вы явно задали вопрос об эффективности, вы можете, очевидно, повторить и фильтровать результаты. Самый простой способ сделать это - fnmatch. Все, что делает glob, вызывает listdir, а затем fnmatch на каждый результат; Вы можете сделать то же самое с несколькими fnmatch вызовов:

for filename in os.listdir('.'): 
    if fnmatch.fnmatch(filename, 'buffer*'): 
     os.remove(filename) 
    # etc. 

И, конечно, вы можете упростить это точно так же, как partofthething упрощена существующий код:

for filename in os.listdir('.'): 
    for pattern in ['buffer*', 'grid*', 'OSMroads*', 
        'newCostSurface*','standsLine*', 'standsReprojected*']: 
     if fnmatch.fnmatch(filename, pattern): 
      os.remove(filename) 

Или:

for filename in os.listdir('.'): 
    if any(fnmatch.fnmatch(filename, pattern) 
      for pattern in ['buffer*', 'grid*', 'OSMroads*', 
          'newCostSurface*','standsLine*', 'standsReprojected*']): 
     os.remove(filename) 

Если вам действительно нужно выжать еще одну крошечную долю процента производительности, вы можете использовать fnmatch.translate для преобразования каждого шаблона в регулярное выражение, а затем слить r egexps в чередование и скомпилировать его, а затем применить этот объект регулярного выражения к каждому имени файла. Но время CPU для fnmatch по сравнению с временем ввода-вывода для чтения объектов каталога, вероятно, настолько мало, что улучшение даже не измеримо.

+0

Очень хороший ответ. Я сам ленивый машинист, я бы использовал «буферную сетку OSMroads и т. Д.» .split() 'вместо списка и' pattern + '*' 'при сопоставлении. Это питонический или слишком ленивый? –

+1

@ ManuelGutierrez: Ну, если это слишком лениво, тогда я бы сказал, что ты в хорошей компании. Обратите внимание, что такие типы stdlib, как ['namedtuple'] (http://docs.python.org/3.4/library/collections.html#collections.namedtuple) и [' enum'] (http://docs.python.org/ 3.4/library/enum.html # functional-api) эффективно имеют встроенный 'split()', потому что все в обсуждениях 'namedtuple' (включая большинство основных разработчиков) записывали' namedtuple ('Point', ' xy z'.split()), и кто-то предположил, что стоит сделать еще короче. – abarnert

+0

Полезно знать, спасибо. –

4

Мне нравится использовать списки, так что я не повторять код, например:

for pattern in ['buffer*','grid*','OSMroads*','newCostSurface*','standsLine*' 
       'standsReprojected*']: 
    for filename in glob.glob(pattern): 
     os.remove(filename) 
Смежные вопросы