Разработка приложения для работы с файлами на Python
Основные подходы к созданию файлового менеджера
Как создать консольный файловый менеджер с базовыми операциями?
Представленный ниже код использует модуль pathlib для удобной работы с путями. Основная идея: реализовать циклическое меню с командами: ls (список), cd (смена директории), cp (копирование), mv (перемещение), rm (удаление). Для каждой команды добавлена обработка ошибок.
import pathlib, shutil, sys
def main():
current = pathlib.Path.cwd()
while True:
print(f"Текущая папка: {current}")
command = input("Введите команду: ").strip().split()
if not command:
continue
cmd = command[0].lower()
try:
if cmd == 'ls':
for item in current.iterdir():
print(item.name)
elif cmd == 'cd':
target = command[1] if len(command)>1 else '.'
new = current / target
new = new.resolve()
if new.is_dir():
current = new
else:
print("Ошибка: не папка")
elif cmd == 'cp':
src, dst = command[1], command[2]
src_path = current / src
dst_path = current / dst
if src_path.is_file():
shutil.copy2(src_path, dst_path)
else:
shutil.copytree(src_path, dst_path)
elif cmd == 'mv':
src, dst = command[1], command[2]
shutil.move(str(current / src), str(current / dst))
elif cmd == 'rm':
target = command[1]
path = current / target
if path.is_file():
path.unlink()
else:
shutil.rmtree(path)
elif cmd == 'exit':
sys.exit(0)
except Exception as e:
print(f"Ошибка: {e}")
Python packaging tools (python packaging tools (инструменты сборки))
Пояснения: pathlib предоставляет объекты Path, которые упрощают операции. shutil используется для копирования и перемещения. В цикле обрабатываются исключения, чтобы программа не падала при ошибках доступа или неверных путях.
Типичные проблемы:
- Пробелы в именах файлов - метод split() разбивает ввод по пробелам. Решение: использовать input() без split или парсить с учётом кавычек.
- Права доступа - исключение PermissionError. Обрабатывается общим except.
- Кодировка вывода - в Windows может возникнуть проблема с кириллицей. Решение: установить кодировку консоли (chcp 65001) или использовать sys.stdout.reconfigure.
Как реализовать файловый менеджер с графическим интерфейсом на tkinter?
Пример ниже создаёт окно с Treeview для отображения файлов, кнопками для навигации и операций. Используется встроенный модуль tkinter и ttk.
import tkinter as tk
from tkinter import ttk, filedialog, messagebox
import pathlib, shutil
class FileManager:
def __init__(self, root):
self.root = root
self.root.title('Файловый менеджер')
self.current_path = pathlib.Path.home()
self.create_widgets()
self.refresh()
def create_widgets(self):
self.tree = ttk.Treeview(self.root, columns=('Name','Size','Type'), show='headings')
self.tree.heading('Name', text='Имя')
self.tree.heading('Size', text='Размер')
self.tree.heading('Type', text='Тип')
self.tree.pack(fill=tk.BOTH, expand=True)
btn_frame = tk.Frame(self.root)
btn_frame.pack()
tk.Button(btn_frame, text='Вверх', command=self.go_up).pack(side=tk.LEFT)
tk.Button(btn_frame, text='Удалить', command=self.delete_item).pack(side=tk.LEFT)
def go_up(self):
self.current_path = self.current_path.parent
self.refresh()
def refresh(self):
for i in self.tree.get_children():
self.tree.delete(i)
try:
for item in self.current_path.iterdir():
name = item.name
size = ''
typ = 'Папка' if item.is_dir() else 'Файл'
if item.is_file():
size = str(item.stat().st_size) + ' B'
self.tree.insert('', tk.END, values=(name, size, typ))
except PermissionError:
messagebox.showerror('Ошибка', 'Нет доступа к папке')
def delete_item(self):
selected = self.tree.selection()
if selected:
name = self.tree.item(selected[0], 'values')[0]
path = self.current_path / name
if messagebox.askyesno('Подтверждение', f'Удалить {name}?'):
try:
if path.is_dir():
shutil.rmtree(path)
else:
path.unlink()
self.refresh()
except Exception as e:
messagebox.showerror('Ошибка', str(e))
root = tk.Tk()
app = FileManager(root)
root.mainloop()
Python online код (онлайн редактор python)
Пояснения: Treeview отображает данные в табличном виде. pathlib.Path.iterdir() получает содержимое папки. При удалении выводится диалог подтверждения. Проблемы: быстродействие при большом количестве файлов (решение - загружать постранично, например через виртуальное дерево).
Как упростить создание графического файлового менеджера с PySimpleGUI?
import PySimpleGUI as sg
import pathlib, shutil
layout = [
[sg.Text('Текущая папка'), sg.Input('', key='-PATH-'), sg.FolderBrowse('Обзор')],
[sg.Listbox(values=[], key='-FILES-', size=(60,20))],
[sg.Button('Копировать'), sg.Button('Удалить'), sg.Button('Выход')]
]
window = sg.Window('Файловый менеджер', layout)
current = pathlib.Path.cwd()
while True:
event, values = window.read()
if event in (sg.WIN_CLOSED, 'Выход'):
break
if event == 'Обзор':
current = pathlib.Path(values['-PATH-'])
try:
files = [p.name for p in current.iterdir()]
window['-FILES-'].update(files)
except Exception as e:
sg.popup_error('Ошибка', str(e))
window.close()
Find python script (поиск python скрипта)
PySimpleGUI значительно сокращает код. Однако имеет ограничения по настройке внешнего вида. Для простого файлового менеджера такой подход оправдан.
Как организовать файловый менеджер через веб-интерфейс?
from flask import Flask, render_template_string, request
import pathlib, shutil
app = Flask(__name__)
BASE = pathlib.Path.cwd()
@app.route('/')
def index():
path = request.args.get('path', '.')
full = (BASE / path).resolve()
try:
items = [{'name': p.name, 'relpath': p.relative_to(BASE).as_posix()} for p in full.iterdir()]
except PermissionError:
items = []
return render_template_string('''
{{ path }}
{% for item in items %}
{% endfor %}
''', path=path, items=items)
if __name__ == '__main__':
app.run(debug=True)
Веб-менеджер удобен для удаленного доступа. Требуется тщательная валидация путей и ограничение доступа во избежание уязвимостей (например, path traversal).
Расширенные примеры и нестандартные сценарии
Асинхронное копирование файлов с asyncio
Когда требуется скопировать множество больших файлов, асинхронный подход позволяет не блокировать основной поток. Используется библиотека aiofiles и asyncio.
import asyncio
import aiofiles
import aiofiles.os
import pathlib
async def copy_file(src, dst):
async with aiofiles.open(src, 'rb') as fsrc:
async with aiofiles.open(dst, 'wb') as fdst:
while True:
chunk = await fsrc.read(65536)
if not chunk:
break
await fdst.write(chunk)
async def main(src_dir, dst_dir):
src = pathlib.Path(src_dir)
dst = pathlib.Path(dst_dir)
tasks = []
for item in src.iterdir():
if item.is_file():
tasks.append(copy_file(item, dst / item.name))
await asyncio.gather(*tasks)
asyncio.run(main('/source', '/dest'))
Результат: все файлы из /source скопированы в /dest асинхронно. (Выполнение завершено без вывода, так как функция ничего не печатает.)
Отслеживание изменений в файловой системе с watchdog
Модуль watchdog позволяет наблюдать за изменениями в директории и реагировать на них.
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
import time
class MyHandler(FileSystemEventHandler):
def on_modified(self, event):
print(f'Изменен: {event.src_path}')
def on_created(self, event):
print(f'Создан: {event.src_path}')
path = '.'
observer = Observer()
observer.schedule(MyHandler(), path, recursive=False)
observer.start()
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
observer.stop()
observer.join()
При создании или изменении файла в текущей папке выводится соответствующее сообщение.
Работа с архивами: упаковка и распаковка zip
import zipfile
import pathlib
def create_zip(source_dir, output_zip):
with zipfile.ZipFile(output_zip, 'w', zipfile.ZIP_DEFLATED) as zf:
for file in pathlib.Path(source_dir).rglob('*'):
zf.write(file, file.relative_to(source_dir))
def extract_zip(zip_path, extract_dir):
with zipfile.ZipFile(zip_path, 'r') as zf:
zf.extractall(extract_dir)
create_zip('./my_folder', './backup.zip')
extract_zip('./backup.zip', './restored')
После выполнения появится backup.zip, а затем папка restored с содержимым.
Рекурсивный поиск файлов по маске
import pathlib
pattern = '*.py'
found = list(pathlib.Path('.').rglob(pattern))
for f in found:
print(f.relative_to('.'))
Вывод всех файлов .py в текущем каталоге и подкаталогах.
Пакетное переименование файлов с использованием регулярных выражений
import pathlib
import re
def rename_files(directory, pattern, replacement):
for file in pathlib.Path(directory).iterdir():
if file.is_file():
new_name = re.sub(pattern, replacement, file.name)
if new_name != file.name:
file.rename(file.parent / new_name)
rename_files('./', r'\s+', '_')
Все файлы в текущей папке с пробелами в имени переименуются: пробелы заменяются на подчеркивание.
Хеширование файлов (MD5) для проверки целостности
import hashlib
def md5_hash(file_path):
h = hashlib.md5()
with open(file_path, 'rb') as f:
for chunk in iter(lambda: f.read(4096), b''):
h.update(chunk)
return h.hexdigest()
print(md5_hash('test.txt'))
d41d8cd98f00b204e9800998ecf8427e (пример для пустого файла)