Я хочу иметь возможность отображать только каталоги внутри какой-либо папки. Это означает, что мне не нужны перечисленные имена файлов и не нужны дополнительные подпапки.
Посмотрим, поможет ли пример. В текущем каталоге у нас есть:
>>> os.listdir(os.getcwd())
['cx_Oracle-doc', 'DLLs', 'Doc', 'include', 'Lib', 'libs', 'LICENSE.txt', 'mod_p
ython-wininst.log', 'NEWS.txt', 'pymssql-wininst.log', 'python.exe', 'pythonw.ex
e', 'README.txt', 'Removemod_python.exe', 'Removepymssql.exe', 'Scripts', 'tcl',
'Tools', 'w9xpopen.exe']
Однако мне не нужно перечислять имена файлов. Мне также не нужны подпапки, такие как \ Lib \ curses. По сути, то, что я хочу, работает со следующим:
>>> for root, dirnames, filenames in os.walk('.'):
... print dirnames
... break
...
['cx_Oracle-doc', 'DLLs', 'Doc', 'include', 'Lib', 'libs', 'Scripts', 'tcl', 'Tools']
Однако мне интересно, есть ли более простой способ достичь тех же результатов. У меня сложилось впечатление, что использование os.walk только для возврата на верхний уровень неэффективно / слишком много.






directories=[d for d in os.listdir(os.getcwd()) if os.path.isdir(d)]
Это можно сократить до filter (os.path.isdir, os.listdir (os.getcwd ())
Есть ли у кого-нибудь информация о том, быстрее ли фильтр или понимание списка? В противном случае это просто субъективный аргумент. Это, конечно, предполагает, что в cwd 10 миллионов каталогов, и производительность является проблемой.
Вот так?
>>>> [path for path in os.listdir(os.getcwd()) if os.path.isdir(path)]
[x for x in os.listdir(somedir) if os.path.isdir(os.path.join(somedir, x))]
Отфильтруйте результат с помощью os.path.isdir () (и используйте os.path.join (), чтобы получить реальный путь):
>>> [ name for name in os.listdir(thedir) if os.path.isdir(os.path.join(thedir, name)) ]
['ctypes', 'distutils', 'encodings', 'lib-tk', 'config', 'idlelib', 'xml', 'bsddb', 'hotshot', 'logging', 'doc', 'test', 'compiler', 'curses', 'site-packages', 'email', 'sqlite3', 'lib-dynload', 'wsgiref', 'plat-linux2', 'plat-mac']
Это требует много обработки по сравнению с очень простой os.walk (). Next () [1]
Отфильтруйте список с помощью os.path.isdir для обнаружения каталогов.
filter(os.path.isdir, os.listdir(os.getcwd()))
Я думаю, что это, безусловно, лучшее сочетание удобочитаемости и краткости в любом из этих ответов.
Это не сработало. Я предполагаю, что os.listdir возвращает имя файла / папки, переданное os.path.isdir, но последнему нужен полный путь.
фильтр быстрее, чем os.walk timeit(os.walk(os.getcwd()).next()[1])1000 loops, best of 3: 734 µs per looptimeit(filter(os.path.isdir, os.listdir(os.getcwd())))1000 loops, best of 3: 477 µs per loop
Комментарий здесь заключается в том, что os.listdir не возвращает абсолютный путь, поэтому filter(os.path.isdir, [os.path.join(base, f) for f in os.listdir(base)]) решил это за меня.
Обратите внимание, что вместо os.listdir(os.getcwd()) предпочтительнее использовать os.listdir(os.path.curdir). На один вызов функции меньше, и он такой же переносимый.
Итак, чтобы завершить ответ, получить список каталогов в папке:
def listdirs(folder):
return [d for d in os.listdir(folder) if os.path.isdir(os.path.join(folder, d))]
Если вы предпочитаете полные пути, используйте эту функцию:
def listdirs(folder):
return [
d for d in (os.path.join(folder, d1) for d1 in os.listdir(folder))
if os.path.isdir(d)
]
Используйте os.walk с функцией элемента next:
next(os.walk('.'))[1]
Для Python <= 2.5 используйте:
os.walk('.').next()[1]
os.walk - это генератор, и при вызове next будет получен первый результат в виде трех кортежей (dirpath, dirnames, filenames). Таким образом, индекс [1] возвращает только dirnames из этого кортежа.
Еще немного описания: это генератор, он не будет ходить по другим каталогам, если вы ему не скажете. Итак .next () [1] в одной строке выполняет то же самое, что и все представления списка. Я бы, вероятно, сделал что-то вроде DIRNAMES=1, а затем next()[DIRNAMES], чтобы облегчить понимание для будущих разработчиков кода.
+1 потрясающее решение. Чтобы указать каталог для просмотра, используйте: os.walk( os.path.join(mypath,'.')).next()[1]
для python v3: next (os.walk ('.')) [1]
если вы собираетесь делать больше, чем обработка текста; т.е. обработка в фактических папках, тогда могут потребоваться полные пути: sorted( [os.path.join(os.getcwd(), item) for item in os.walk(os.curdir).next()[1]] )
почему точка? next(os.walk('.'))[1]
. указывает текущий каталог. Это эквивалент os.getcwd().
будучи здесь новичком, я пока не могу напрямую комментировать, но вот небольшое исправление, которое я хотел бы добавить в следующую часть ΩΤΖΙΟΥ ответ:
If you prefer full pathnames, then use this function:
def listdirs(folder): return [ d for d in (os.path.join(folder, d1) for d1 in os.listdir(folder)) if os.path.isdir(d) ]
для тех, кто все еще использует python <2.4: внутренняя конструкция должна быть списком, а не кортежем, и поэтому должна читаться так:
def listdirs(folder):
return [
d for d in [os.path.join(folder, d1) for d1 in os.listdir(folder)]
if os.path.isdir(d)
]
в противном случае возникает синтаксическая ошибка.
Я знаю, что это было давно, но этот первый пример мне очень помог.
Вы получаете синтаксическую ошибку, потому что ваша версия не поддерживает выражения генератора. Они были введены в Python 2.4, тогда как понимание списков было доступно с Python 2.0.
Просто добавлю, что использование os.listdir () не "требуется много обработки по сравнению с очень простой os.walk (). next () [1]". Это потому, что os.walk () внутренне использует os.listdir (). Фактически, если вы протестируете их вместе:
>>>> import timeit
>>>> timeit.timeit("os.walk('.').next()[1]", "import os", number=10000)
1.1215229034423828
>>>> timeit.timeit("[ name for name in os.listdir('.') if os.path.isdir(os.path.join('.', name)) ]", "import os", number=10000)
1.0592019557952881
Фильтрация os.listdir () выполняется немного быстрее.
В Python 3.5 есть более быстрый способ получения содержимого каталога: python.org/dev/peps/pep-0471
pep-0471 - пакет scandir - доступен для Python 2.6 и более поздних версий в качестве устанавливаемого пакета на PyPI. Он предлагает замену os.walk и os.listdir, которая работает намного быстрее.
Для списка полных имен я предпочитаю эту версию другим решения здесь:
def listdirs(dir):
return [os.path.join(os.path.join(dir, x)) for x in os.listdir(dir)
if os.path.isdir(os.path.join(dir, x))]
Более простой и элегантный способ - использовать это:
import os
dir_list = os.walk('.').next()[1]
print dir_list
Запустите этот скрипт в той же папке, для которой вы хотите получить имена папок. Он даст вам только точное имя папок (и это тоже без полного пути к папкам).
Кажется, это тоже работает (по крайней мере, на Linux):
import glob, os
glob.glob('*' + os.path.sep)
+1 для glob. Это может сэкономить вам много кода, особенно итераций, и очень похоже на использование терминала UNIX (ls).
Вместо glob.glob ('*' + os.path.sep) вы можете написать [dir вместо dir в glob.glob ("*"), если os.path.isdir (dir)]
Более безопасный вариант, который не подведет, когда нет каталога.
def listdirs(folder):
if os.path.exists(folder):
return [d for d in os.listdir(folder) if os.path.isdir(os.path.join(folder, d))]
else:
return []
scanDir = "abc"
directories = [d for d in os.listdir(scanDir) if os.path.isdir(os.path.join(os.path.abspath(scanDir), d))]
-- This will exclude files and traverse through 1 level of sub folders in the root
def list_files(dir):
List = []
filterstr = ' '
for root, dirs, files in os.walk(dir, topdown = True):
#r.append(root)
if (root == dir):
pass
elif filterstr in root:
#filterstr = ' '
pass
else:
filterstr = root
#print(root)
for name in files:
print(root)
print(dirs)
List.append(os.path.join(root,name))
#print(os.path.join(root,name),"\n")
print(List,"\n")
return List
Используя понимание списка,
[a for a in os.listdir() if os.path.isdir(a)]
Я думаю это самый простой способ
Python 3.4 представил модуль pathlib в стандартной библиотеке, которая обеспечивает объектно-ориентированный подход для обработки путей файловой системы:
from pathlib import Path
p = Path('./')
[f for f in p.iterdir() if f.is_dir()]
FWIW, подход os.walk почти в 10 раз быстрее, чем подходы к пониманию и фильтрации списков:
In [30]: %timeit [d for d in os.listdir(os.getcwd()) if os.path.isdir(d)]
1.23 ms ± 97.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [31]: %timeit list(filter(os.path.isdir, os.listdir(os.getcwd())))
1.13 ms ± 13.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [32]: %timeit next(os.walk(os.getcwd()))[1]
132 µs ± 9.34 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
Вы также можете использовать os.scandir:
with os.scandir(os.getcwd()) as mydir:
dirs = [i.name for i in mydir if i.is_dir()]
Если вам нужен полный путь, вы можете использовать i.path.
Using scandir() instead of listdir() can significantly increase the performance of code that also needs file type or file attribute information, because os.DirEntry objects expose this information if the operating system provides it when scanning a directory.
os.walk () использует функцию генератора и не будет неэффективной, если вы используете ее только для верхнего уровня.