Рубрики
Без рубрики

Python: Проверьте, пуст ли файл или каталог

В этом уроке мы узнаем, как проверить, пуст ли файл или каталог в Python на примерах. Это можно сделать с помощью модулей os и path lib.

Автор оригинала: Tapan Pandey.

Python: Проверьте, пуст ли файл или каталог

Вступление

Python имеет набор встроенных библиотечных объектов и функций, которые помогут нам в решении этой задачи. В этом уроке мы узнаем, как проверить, пуст ли файл или каталог в Python.

Различайте файл и каталог

Когда мы хотим проверить, является ли путь пустым или нет, мы хотим знать, является ли он файлом или каталогом , поскольку это влияет на подход, который мы хотим использовать.

Допустим, у нас есть две переменные-заполнители dirpath и file path , идентифицирующие локальный каталог и файл:

dirpath = '/mnt/f/code.books/articles/python'
filepath = '/mnt/f/code.books/articles/python/code/file_dir.py'

Использование os.path

Python предоставляет модуль os , который представляет собой стандартный пакет функций, объектов и констант Python для работы с операционной системой.

os.path предоставляет нам функции isfile() и isdir () , чтобы легко отличить файл от каталога:

import os

dirpath = '/mnt/f/code.books/articles/python'
filepath = '/mnt/f/code.books/articles/python/code/file_dir.py'

os.path.isfile(dirpath) # False
os.path.isdir(dirpath) # True
os.path.isfile(filepath) # True
os.path.isdir(filepath) # False

Обе эти функции возвращают значение Boolean .

Использование pathlib

Python 3.4 представил модуль pathlib , который предоставляет объектно-ориентированный интерфейс для работы с файловыми системами.

path lib упрощает работу с файловыми системами по сравнению с os или os.path .

Класс Path модуля pathlib принимает путь в качестве аргумента и возвращает объект Path , который можно легко запросить или связать с помощью методов и атрибутов:

from pathlib import Path

dirpath = '/mnt/f/code.books/articles/python'
filepath = '/mnt/f/code.books/articles/python/code/file_dir.py'

Path(dirpath).is_file() # False
Path(dirpath).is_dir() # True
Path(filepath).is_file() # True
Path(dirpath).is_file() # False

Здесь мы проверяем, является ли объект Path файлом или каталогом.

Проверьте, пуст ли файл

Пустой файл или файл с нулевым байтом-это любой файл, который не содержит данных или содержимого. Файл может быть любого типа. Некоторые файлы (например, музыкальные файлы) могут не иметь данных, но все же содержать метаданные (например, автор). Такие файлы не могут рассматриваться как пустой файл.

Можно быстро создать пустой файл в Linux и Mac OS:

$ touch emptyfile

Или на окнах:

$ type nul > emptyfile

Давайте теперь определим переменные – пустой файл и непустой файл , указывающие на пустой файл с нулевыми байтами и непустой файл размером в один байт:

emptyfile = '/mnt/f/code.books/articles/python/emptyfile'
nonemptyfile = '/mnt/f/code.books/articles/python/onebytefile'

Давайте посмотрим на тип и размер этих файлов:

$ ls -l
-rwxrwxrwx 1 root root   0 Sep 10 18:06 emptyfile
-rwxrwxrwx 1 root root   1 Sep 10 18:08 onebytefile
$ file emptyfile
emptyfile: empty
$ file onebytefile
onebytefile: very short file (no magic)

Использование os.stat

Кроме того, мы можем использовать модуль Python os для проверки этой информации. Функция os.stat() возвращает объект stat_result . Этот объект в основном представляет собой структуру данных, которая представляет собой набор свойств файла:

import os

emptyfile = '/mnt/f/code.books/articles/python/emptyfile'
nonemptyfile = '/mnt/f/code.books/articles/python/onebytefile'

result = os.stat(nonemptyfile)
result.st_size # 1

result = os.stat(emptyfile)
result.st_size # 0

Использование os.path

Модуль Python os.path позволяет очень легко работать с путями к файлам. Помимо проверки наличия пути или определения их типа, мы также можем получить размер файла, указанного в виде строки.

os.path.getsize() возвращает размер файла, указанного как path-like-object и намного проще в использовании, чем os.stat() :

import os

emptyfile = '/mnt/f/code.books/articles/python/emptyfile'
nonemptyfile = '/mnt/f/code.books/articles/python/onebytefile'

os.path.getsize(emptyfile) # 0

os.path.getsize(nonemptyfile) # 1

Использование pathlib

Если мы работаем на Python 3.4 или выше, мы можем использовать модуль pathlib для получения размера файла. Это в основном заменяет модуль os . Path.stat() возвращает свойство stat_result объекта Path , эквивалентное возвращаемому значению os.stat() :

from pathlib import Path

emptyfile = '/mnt/f/code.books/articles/python/emptyfile'
nonemptyfile = '/mnt/f/code.books/articles/python/onebytefile'

print('File stats: ' + Path(emptyfile).stat())

print('File size: ' + Path(emptyfile).stat().st_size + ' byte(s)')

print('File stats: ' + Path(nonemptyfile).stat())

print('File size: ' + Path(nonemptyfile).stat().st_size + ' byte(s)')

Это приводит к:

File stats: os.stat_result(st_mode=33279, st_ino=14355223812249048, st_dev=17, st_nlink=1, st_uid=0, st_gid=0, st_size=0, st_atime=1600087010, st_mtime=1600087010, st_ctime=1600087010)
File size: 0 byte(s)

File stats: os.stat_result(st_mode=33279, st_ino=5629499534218713, st_dev=17, st_nlink=1, st_uid=0, st_gid=0, st_size=1, st_atime=1600088120, st_mtime=1600088072, st_ctime=1600088072)
File size: 1 byte(s)

Проверьте, пуст ли каталог

Каталог, который не содержит других файлов или подкаталогов, является пустым каталогом. Однако каждый каталог (даже пустой) содержит следующие 2 записи:

  • . ( произносится точка ) ссылается на текущий каталог и полезен в таких операциях, как поиск чего-то внутри текущего каталога
  • .. ( произносится двойная точка ) ссылается на родительский каталог текущего каталога, требуется отступить от текущего каталога

Определим две переменные – пустой каталог и непустой каталог , указывающие на пустой и непустой каталог:

emptydirectory = '/mnt/f/code.books/articles/python/markdown'
nonemptydirectory = '/mnt/f/code.books/articles/python/code'

В пустом каталоге нет никаких элементов:

$ pwd
/mnt/f/code.books/articles/python/markdown
$ ls -la
total 0
drwxrwxrwx 1 root root 512 Sep 11 11:52 .
drwxrwxrwx 1 root root 512 Sep 10 20:22 ..

Непустой каталог имеет один файл:

$ pwd
/mnt/f/code.books/articles/python/code
$ ls -la
total 0
drwxrwxrwx 1 root root 512 Sep 14 11:02 .
drwxrwxrwx 1 root root 512 Sep 14 18:22 ..
-rwxrwxrwx 1 root root 425 Sep 14 12:27 file_dir.py

Использование os.listdir()

Функция os.listdir() возвращает последовательность, содержащую имена всех элементов, найденных в пути к каталогу, переданном в качестве аргумента. Он не включает в себя . и .. записи:

import os

os.listdir(emptydirectory) # []
os.listdir(nonemptydirectory) # ['file_dir.py']

Вычисление длины возвращаемого списка легко определяет, является ли каталог пустым или нет. Пустой каталог всегда имеет нулевую длину:

import os

print(len(os.listdir(nonemptydirectory))) # 1
print(len(os.listdir(emptydirectory))) # 0

Использование os.scandir()

Функция os.listdir() полезна, когда вам нужна целая куча имен записей в виде списка для дальнейшей обработки. Однако, чтобы проверить, есть ли хотя бы одна запись, нам не нужен список всех файлов внутри.

Если каталог огромен, то выполнение функции os.listdir() займет много времени, тогда как до тех пор, пока существует более 0 итак, на наш вопрос дан ответ.

На помощь приходит функция os.scandir () , которая возвращает ленивую итерацию или генератор.

Генераторы возвращают итераторы, которые могут быть зациклены, как обычные итераторы, такие как список. Но в отличие от списка, набора или словаря, они не хранят в памяти целую кучу значений и вместо этого возвращают новое значение по запросу.

Этот подход примерно в 200 раз быстрее для каталогов с ~ 1000 файлами.

Поэтому вместо того, чтобы зацикливаться на всей структуре каталогов, мы можем использовать os.scandir () , чтобы проверить, есть ли хотя бы одна запись, найденная в пути к каталогу:

import os

emptydirectory = '/mnt/f/code.books/articles/python/markdown'
nonemptydirectory = '/mnt/f/code.books/articles/python/code'

print(next(os.scandir(emptydirectory), None))
print(next(os.scandir(nonemptydirectory), None)) # 

Мы используем next() , которая является встроенной функцией для извлечения следующего доступного элемента из ленивого итератора , возвращаемого os.scandir() . Поскольку пустой каталог не имеет доступных элементов – он возвращает None , тогда как для непустого каталога он возвращает os.DirEntry объект.

Использование pathlib

Предпочтительным подходом к модулю os является модуль pathlib . Мы будем использовать pathlib.Path.iterdir() , который не только проще, но и намного проще в использовании, чем os.listdir() или os.scandir() .

Он возвращает ленивый итеративный или генераторный объект , очень похожий на os.scandir () , который перебирает файлы в пути каталога, переданном в качестве аргумента:

from pathlib import Path
print(Path(emptydirectory).iterdir()) # 

Используя next() , мы пытаемся получить следующий доступный элемент. С None в качестве default return item, next() не вызовет StopIteration исключение в случае отсутствия элемента в коллекции:

print(next(Path(emptydirectory).iterdir(), None)) # None
print(next(Path(nonemptydirectory).iterdir(), None)) # /mnt/f/code.books/articles/python/code/file_dir.py

Большинство встроенных функций Python работают с iterables , включая any() функцию, которая возвращает обратно True если iterable имеет хотя бы один элемент, который может быть оценен как True :

from pathlib import Path
print(any(Path(emptydirectory).iterdir()) # False
print(any(nonemptydirectory).iterdir()) # True

Вывод

В этом уроке мы рассмотрели, как различать файлы и каталоги, после чего проверили их пустоту.

Это можно сделать с помощью модулей os или path lib и их удобных функций и классов.