- Python — The Filesystem
- Zip and Unzip
- Downloading Code from Github
- Search
- Delete Files
- 8 команд для Python по работе с файлами и файловой системой, которые обязательно нужно знать
- Показать текущий каталог
- Проверяем, существует файл или каталог
- Объединение компонентов пути
- Создание директории
- Показываем содержимое директории
- Перемещение файлов
- Копирование файлов
- Удаление файлов и папок
Python — The Filesystem
We can use those properties to further process the file:
from pathlib import Path from datetime import datetime path = Path('files/test1.md') stats = path.stat() # Get file size and set unit def get_size(): file_bytes = stats.st_size file_kilobytes = file_bytes / 1024 file_megabytes = file_kilobytes / 1024 if file_megabytes > 1: return str(file_megabytes) + ' MB' elif file_kilobytes > 1: return str(file_kilobytes) + ' kB' else: return str(file_bytes) + ' B' # Get date last accessed and process timestamp last_accessed = stats.st_ctime date_accessed = datetime.fromtimestamp(last_accessed).strftime("%Y-%m-%d_%H:%M:%S") # Append timestamp to file with open(path, 'a') as file: file.write('\n' + date_accessed + ' | ' + get_size() + '\n')
Zip and Unzip
Write to zip container and add timestamp:
from pathlib import Path from datetime import datetime import zipfile root_dir = Path('files/projectA') # get timestamp for archive name now = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") archive_name = now + '_archive.zip' archive_path = root_dir / Path(archive_name) # write all markdown pages in dir to zip container with zipfile.ZipFile(archive_path, 'w') as zf: for path in root_dir.glob('*.md'): zf.write(path) # delete source files # path.unlink()
Unzip all containers from a directory recursively to individual destination folder:
# unzip all containers in root dir recursively destination_path = Path('files/unzipped') for path in root_dir.rglob('*.zip'): with zipfile.ZipFile(path, 'r') as zf: sub_dir = destination_path / Path(path.stem) zf.extractall(path=sub_dir)
Downloading Code from Github
Navigate to your project page and select the latest release to get the download URL. Then add a Python script to handle the HTTP download:
import requests import tarfile import os version = '1.4.19' url = 'https://github.com/hashicorp/terraform-provider-nomad/archive/refs/tags/v' + version + '.tar.gz' archive = requests.get(url).content with open('src/terraform_provider_nomad.tar.gz', 'wb') as file: file.write(archive) # extract all archive_extraction = tarfile.open('src/terraform_provider_nomad.tar.gz') archive_extraction.extractall('src') archive_extraction.close() # single file extraction container_path = 'terraform-provider-nomad-' + version + '/CHANGELOG.md' file_extraction = tarfile.open('./src/terraform_provider_nomad.tar.gz', 'r:gz') file_extraction.extract(container_path,'./version') file_extraction.close() # output os.remove("src/terraform_provider_nomad.tar.gz") print('INFO :: All files downloaded and extracted to src/terraform-provider-nomad-' + version) with open('version/terraform-provider-nomad-' + version + '/CHANGELOG.md', 'r') as file: print(file.read())
Search
Find all files and folders that contain a search term:
from pathlib import Path root_dir = Path('files') search_term = 'test' for path in root_dir.rglob('*'): if search_term in path.stem: print(path.absolute())
Delete Files
Delete all zip container recursively from a root directory securely:
from pathlib import Path root_dir = Path('files/projectA') for path in root_dir.rglob("*.zip"): with open(path, 'wb') as file: # overwrite with empty bytes to delete secure file.write(b'') # delete all zip files path.unlink()
And wrapping everything up into a PyQT6 desktop application:
from PyQt6.QtWidgets import ( QApplication, QVBoxLayout, QHBoxLayout, QPushButton, QWidget, QLabel, QFileDialog ) from pathlib import Path def open_files(): global filenames # return absolute path of user selected files filenames, _ = QFileDialog.getOpenFileNames(window, 'Select files') message.setText('\n'.join(filenames)) def delete_files(): for filename in filenames: path = Path(filename) with open(path, 'wb') as file: file.write(b'') path.unlink() message.setText('Deleted!') app = QApplication([]) window = QWidget() window.setWindowTitle('Destroyer of Worlds') # set layout layout_main = QVBoxLayout() layout_top_container = QHBoxLayout() layout_main.addLayout(layout_top_container) layout_bottom_container = QHBoxLayout() layout_main.addLayout(layout_bottom_container) # select files to delete description = QLabel('Select files for deletion: ') layout_top_container.addWidget(description) open_btn = QPushButton('Open Files') open_btn.setToolTip('Open files and select for deletions.') layout_top_container.addWidget(open_btn) open_btn.clicked.connect(open_files) # delete selected files del_btn = QPushButton('Delete Files') del_btn.setToolTip('Permanently delete all selected files.') layout_bottom_container.addWidget(del_btn) del_btn.clicked.connect(delete_files) # show filepath of selected files message = QLabel('') layout_main.addWidget(message) # run app window.setLayout(layout_main) window.show() app.exec()
8 команд для Python по работе с файлами и файловой системой, которые обязательно нужно знать
Python становится все популярнее благодаря относительной простоте изучения, универсальности и другим преимуществам. Правда, у начинающих разработчиков нередко возникают проблемы при работе с файлами и файловой системой. Просто потому, что они знают не все команды, которые нужно знать.
Эта статья предназначена как раз для начинающих разработчиков. В ней описаны 8 крайне важных команд для работы с файлами, папками и файловой системой в целом. Все примеры из этой статьи размещены в Google Colab Notebook (ссылка на ресурс — в конце статьи).
Показать текущий каталог
Самая простая и вместе с тем одна из самых важных команд для Python-разработчика. Она нужна потому, что чаще всего разработчики имеют дело с относительными путями. Но в некоторых случаях важно знать, где мы находимся.
Относительный путь хорош тем, что работает для всех пользователей, с любыми системами, количеством дисков и так далее.
Так вот, для того чтобы показать текущий каталог, нужна встроенная в Python OS-библиотека:
Ее легко запомнить, так что лучше выучить один раз, чем постоянно гуглить. Это здорово экономит время.
Имейте в виду, что я использую Google Colab, так что путь /content является абсолютным.
Проверяем, существует файл или каталог
Прежде чем задействовать команду по созданию файла или каталога, стоит убедиться, что аналогичных элементов нет. Это поможет избежать ряда ошибок при работе приложения, включая перезапись существующих элементов с данными.
Функция os.path.exists () принимает аргумент строкового типа, который может быть либо именем каталога, либо файлом.
В случае с Google Colab при каждом запуске создается папка sample_data. Давайте проверим, существует ли такой каталог. Для этого подойдет следующий код:
Эта же команда подходит и для работы с файлами:
Если папки или файла нет, команда возвращает false.
Объединение компонентов пути
В предыдущем примере я намеренно использовал слеш «/» для разделителя компонентов пути. В принципе это нормально, но не рекомендуется. Если вы хотите, чтобы ваше приложение было кроссплатформенным, такой вариант не подходит. Так, некоторые старые версии ОС Windows распознают только слеш «\» в качестве разделителя.
Но не переживайте, Python прекрасно решает эту проблему благодаря функции os.path.join (). Давайте перепишем вариант из примера в предыдущем пункте, используя эту функцию:
os.path.exists(os.path.join('sample_data', 'README.md'))
Создание директории
Ну а теперь самое время создать директорию с именем test_dir внутри рабочей директории. Для этого можно использовать функцию
os.mkdir():
Давайте посмотрим, как это работает на практике.
Если же мы попытаемся создать каталог, который уже существует, то получим исключение.
Именно поэтому рекомендуется всегда проверять наличие каталога с определенным названием перед созданием нового:
if not os.path.exists('test_dir'): os.mkdir('test_dir')
Еще один совет по созданию каталогов. Иногда нам нужно создать подкаталоги с уровнем вложенности 2 или более. Если мы все еще используем os.mkdir (), нам нужно будет сделать это несколько раз. В этом случае мы можем использовать os.makedirs (). Эта функция создаст все промежуточные каталоги так же, как флаг mkdir -p в системе Linux:
os.makedirs(os.path.join('test_dir', 'level_1', 'level_2', 'level_3'))
Показываем содержимое директории
Еще одна полезная команда — os.listdir(). Она показывает все содержимое каталога.
Команда отличается от os.walk (), где последний рекурсивно показывает все, что находится «под» каталогом. os.listdir () намного проще в использовании, потому что просто возвращает список содержимого:
В некоторых случаях нужно что-то более продвинутое — например, поиск всех CSV-файлов в каталоге «sample_data». В этом случае самый простой способ — использовать встроенную библиотеку glob:
from glob import globlist(glob(os.path.join('sample_data', '*.csv')))
Перемещение файлов
Самое время попробовать переместить файлы из одной папки в другую. Рекомендованный способ — еще одна встроенная библиотека shutil.
Сейчас попробуем переместить все CSV-файлы из директории «sample_data» в директорию «test_dir». Ниже — пример кода для выполнения этой операции:
import shutilfor file in list(glob(os.path.join('sample_data', '*.csv'))): shutil.move(file, 'test_dir')
Кстати, есть два способа выполнить задуманное. Например, мы можем использовать библиотеку OS, если не хочется импортировать дополнительные библиотеки. Как os.rename, так и os.replace подходят для решения задачи.
Но обе они недостаточно «умные», чтобы позволить перемесить файлы в каталог.
Чтобы все это работало, нужно явно указать имя файла в месте назначения. Ниже — код, который это позволяет сделать:
for file in list(glob(os.path.join('test_dir', '*.csv'))): os.rename( file, os.path.join( 'sample_data', os.path.basename(file) ))
Здесь функция os.path.basename () предназначена для извлечения имени файла из пути с любым количеством компонентов.
Другая функция, os.replace (), делает то же самое. Но разница в том, что os.replace () не зависит от платформы, тогда как os.rename () будет работать только в системе Unix / Linux.
Еще один минус — в том, что обе функции не поддерживают перемещение файлов из разных файловых систем, в отличие от shutil.
Поэтому я рекомендую использовать shutil.move () для перемещения файлов.
Копирование файлов
Аналогичным образом shutil подходит и для копирования файлов по уже упомянутым причинам.
Если нужно скопировать файл README.md из папки «sample_data» в папку «test_dir», поможет функция shutil.copy():
shutil.copy( os.path.join('sample_data', 'README.md'), os.path.join('test_dir') )
Удаление файлов и папок
Теперь пришел черед разобраться с процедурой удаления файлов и папок. Нам здесь снова поможет библиотека OS.
Когда нужно удалить файл, нужно воспользоваться командой os.remove():
os.remove(os.path.join('test_dir', 'README(1).md'))
Если требуется удалить каталог, на помощь приходит os.rmdir():
os.rmdir(os.path.join('test_dir', 'level_1', 'level_2', 'level_3'))
Однако он может удалить только пустой каталог. На приведенном выше скриншоте видим, что удалить можно лишь каталог level_3. Что если мы хотим рекурсивно удалить каталог level_1? В этом случае зовем на помощь shutil.
Функция shutil.rmtree() сделает все, что нужно:
shutil.rmtree(os.path.join('test_dir', 'level_1'))
Пользоваться ею нужно с осторожностью, поскольку она безвозвратно удаляет все содержимое каталога.
Собственно, на этом все. 8 важных операций по работе с файлами и каталогами в среде Python мы знаем. Что касается ссылки, о которой говорилось в анонсе, то вот она — это Google Colab Network с содержимым, готовым к запуску.