Разработка файлового менеджера на языке Python
Автор: Глебов С.И., Ивлиева И.А.
Журнал: Форум молодых ученых @forum-nauka
Статья в выпуске: 9 (37), 2019 года.
Бесплатный доступ
Статья посвящена разработке файлового менеджера на языке Python. При разработке выполняются поставленные задачи. При выполнении каждой задачи подробно расписывается, что было добавлено и как это работает.
Программирование, графический интерфейс, буфер
Короткий адрес: https://sciup.org/140287036
IDR: 140287036
Текст научной статьи Разработка файлового менеджера на языке Python
Актуальность: Файловый менеджер – самый удобный, на данный момент, способ взаимодействия с файлами. Он позволяет за довольно короткое время выполнить множество операций, и что самое главное, за счёт реализации графического интерфейса рядовому пользователю всё становится интуитивно понятно.
Объект исследования: Файловый менеджер.
Предмет исследования: Операционная система.
Цель: закрепление и углубление теоретических знаний в области современных операционных систем.
Задачи:
-
1) проектирование файлового менеджера;
-
2) разработка графического интерфейса;
-
3) разработка ПО;
-
4) обеспечение минимального функционала;
-
5) добавление основного функционала;
-
6) тестирование разработанного ПО;
-
7) формирование отчёта.
-
1 Выполненные задания1.1 Задание 1 - Проектирование Файлового менеджера. Выбор средств разработки и среды разработки
При выполнении работы хотелось бы писать максимально лаконичный код. И Python позволяет это сделать. Это можно увидеть на сравнении кода на Python и Java (рис. 1), который открывает файл и сохраняет его содержимое в переменную:

Рис. 1 - Сравнение Java и Python кода
И так как при выполнении данной работы придется реализовывать графический интерфейс, Python будет оптимальным решением из-за относительной простоты построения этого интерфейса и намного большей легковесности, относительно библиотек из Java таких как Swing и JavaFX, которые используют достаточно большое количество ресурсов.
Поэтому я выбираю язык Python и среду разработки «PyCharm»
-
1.2 Задание 2 - Разработка графического интерфейса
На данном этапе проектирования был разработан графический интерфейс программы (рис. 2).
■ ' FlleManager File Edit Tools View Help |
- □ X |
||
Name Size TyPe
|
Date Modified 09.06201914:18 09.062019 14:22 09.062019 14:22 09.062019 14:22 |
Рис. 2 - Графический интерфейс программы
-
1.3 Задание 3 - Разработка ПО
Создается корневая папка как среда работы Файлового менеджера. Создается папка «System», содержит все необходимые файлы для работы файлового менеджера. Так же создаются рабочие папки. Сделать основное и контекстное меню.
Были созданы каталоги System и несколько пользовательских директорий, в которых находятся, соответственно, файлы приложения и пользовательские файлы.
Были реализованы методы перехода в директорию (рис. 3), создания файла (рис. 6) и папки (рис. 5), копирования (рис. 7), удаления (рис. 9), вставки (рис. 8) и возврата в предыдущую директорию (рис. 4).
Метод перехода в директорию (рис. 3): в данном методе мы получаем индекс папки из списка, которую мы хотим перейти, получаем её путь и отображаем в TreeView эту директорию.
def open_script(self):
Рис. 3 - Метод перехода в директорию
Метод возврата в предыдущую директорию (рис. 4): в данном методе мы делим текущий путь по разделителю и удаляем последний элемент, после чего объединяем оставшиеся элементы в строку и отображаем директорию, находящуюся по этому пути, в TreeView def back_script(self): new_paths = self.current_path.split(' /')
print(self.current_path)
new_path = for i in range(len(new_paths) - 1): new_path += new_paths[i] + '/'
Рис. 4 - Метод возврата в предыдущую директорию
Метод создания папки (рис. 5): в данном методе мы получаем индекс папки, в которой мы хотим создать папку, из списка. После чего получаем её путь и добавляем к её пути название новой папки (если такая папка уже существует, то добавляется индекс по числу папок с таким именем).
def create_dir(self):
index = self.treeView.currentindex()
path_index = 0
new_j>ath = path + 1\\new_folder'
path_index += 1
return
Рис. 5 - Метод создания папки
Метод создания файла (рис. 6): в данном методе мы получаем индекс папки, в которой мы хотим создать файл, из списка. После чего получаем её путь и добавляем к её пути название нового файла (если такой файл уже существует, то добавляется индекс по числу файлов с таким именем).
def create_file(self):
new_path = path + '/new_file'
open(new_path, 'w').close()
Рис 6 - Метод создания файла
Метод копирования (рис. 7): в данном методе мы получаем индекс элемента, который мы хотим скопировать (папка или файл), из списка. После чего получаем его путь и копируем его в строку-буфер.
self.buffer_string = path return
Рис. 7 - Метод копирования
Метод вставки (рис. 8): в данном методе мы получаем индекс папки, в которую хотим вставить скопированный элемент, из списка. После чего копируем элемент из пути в строке-буфере в путь выбранной папки.
def paste_3cript(self):
Рис. 8 - Метод вставки
Метод удаления (рис. 9): в данном методе мы получаем индекс элемента, который хотим удалить (папка или файл), из списка. После чего получаем его путь и удаляем элемент по данному пути.
def delete_script(self):
if not path.__contains__('System'):
Рис. 9 - Метод удаления
Все эти методы вызываются из контекстного меню, которое было реализовано с помощью переопределённого метода EventFilter (рис. 10), который принимает ссылки на объект и событие, и обрабатывает их:
def eventFilter(self, obj, event):
if event.type() = QtCore.QEvent.ContextMenu and obj is self.treeView: menu = QtWidgets.QMenu() change_root_j>ath = QtWidgets.QAction(1 Open', menu) menu.addAction(change_root_path) create_folder = QtWidgets.QAction('Create', menu) menu.addAction(create_folder) create_file = QtWidgets.QAction('Create File1, menu) menu.addAction(create_file) copy_folder = QtWidgets.QAction('Copy', menu) menu.addAction(copy_folder) paste_folder = QtWidgets.QAction('Paste', menu) menu.addAction(paste_folder) delete_f older = QtWidgets.QAction('Delete', menu) menu.addAction(delete_folder) back_path = QtWidgets.QAction('Back', menu) menu.addAction(back_path) action = menu.exec_(event.globalPos()) if action “ create_folder:
self.create_dir()
elif action = copy_folder: self.copy_script()
elif action = paste_folder: self.paste_script()
elif action = delete_folder: self.delete_script()
elif action = change_root_path: self.open_script()
elif action = back_path: self.back_script() elif action = create_file: self.create_file()
Рис. 10 - Метод EventFilter
Пример контекстного меню (рис. 11):
-
■ FlleManager
File Edit Tools View Help
Name |
Size |
Type |
Date Modified |
System |
File Folder |
09.06.2019 14:18 |
|
folder! |
File Folder |
09.06.2019 14:22 |
|
folde * |
File Folder |
09.06.2019 14:22 |
|
fol de |
Open |
File Folder |
09.06.2019 14:22 |
Create
Create File
Copy
Paste
Delete
Back
Рис. 11 - Контекстное меню
Создаются несколько меню с кнопками для них, к которым привязываются действия (рис. 12):
-
# тели
mainMenu = self.menuBar()
fileMenu = mainMenu.addMenu('File')
open_button = QtWidgets.Qiction('Open', fileMenu)
fileMenu.addiction(open_button)
close_button = QtWidgets.Qiction('Close', fileMenu)
fileMenu.addiction(close_button)
editMenu = mainMenu.addMenu('Edit')
change_log_name_button = QtWidgets.Qiction('Change Log Name', editMenu) change_log_name_button.triggered.connect(self.open_change_log_name) editMenu.addiction(change_log_name_button)
toolsMenu = mainMenu.addMenu('Tools')
task_manager_button = QtWidgets.Qiction('Task Manager', toolsMenu)
task_manager_button.triggered.connect(self.open_task_manager)
toolsMenu.addiction(task_manager_button)
calculator_button = QtWidgets.Qiction('Calculator', toolsMenu)
calculator_button.triggered.connect(self.open_calculator)
toolsMenu.addiction(calculator_button)
paint_button = QtWidgets.Qiction('Paint', toolsMenu)
paint_button.triggered.connect(self.open_paint)
toolsMenu.addiction(paint_button)
viewMenu = mainMenu.addMenu('View')
processes_button = QtWidgets.Qiction('Processes', viewMenu)
processes_button.triggered.connect(self.print_process)
viewMenu.addiction(processes_button)
pageError_button = QtWidgets.Qiction('Page Error', viewMenu)
pageError_button.triggered.connect(self.get_errors)
viewMenu.addiction(pageError_button)
helpMenu = mainMenu.addMenu('Help')
about_button = QtWidgets.Qiction('About', helpMenu)
about_button.triggered.connect(self.open_about)
helpMenu.addiction(about_button)
Рис. 12 - Реализация основного меню
Пример основного меню (рис. 13):
■ FlleManager
File |
Edit |
Tools |
View Help |
|||||
Task Manager |
||||||||
> |
Name Sy |
Calculator Paint |
Type File Folder |
Date Modified 09.06.2019 14:18 |
||||
> |
folder! |
File Folder |
09.06.2019 14:22 |
|||||
> | |
folder2 |
File Folder |
09.06.201914:22 |
|||||
> |
folderS |
File Folder |
09.06.2019 14:22 |
Рис. 13 - Основное меню
-
1.4 Задание 4 - Обеспечение минимального функционала
С помощью приложения обеспечить возможность создания нового процесса (всплывающее окно), которое будет в дальнейшем отображать информацию основного функционала (или части его). Позволить через приложение запуск встроенных системных утилит ОС. Сохранение протокола запущенных в период работы Файлового менеджера процессов в текстовом файле (имя процесса и время старта). Имя файла задается пользователем.
Были реализованы такие методы как: вызов системных утилит (Диспетчер задач, калькулятор и paint), логирование процессов, запущенных во время работы приложения и окно c информацией о программе.
Метод открытия диспетчера задач (рис. 14): открываем диспетчер задач, с помощью библиотеки os.
I def open_task_manager(self):
оз.system(r'C:Windows\system32\taskmgr.exe1)
Рис. 14 - Метод открытия диспетчера задач
Метод открытия калькулятора (рис. 15): открываем калькулятор, с помощью библиотеки os.
I def open_calculator(self):
Рис. 15 - Метод открытия калькулятора
Метод открытия paint (рис. 16): открываем paint, с помощью библиотеки os.
I def open_paint(self):
Рис. 16 - Метод открытия paint
Эти 3 метода вызываются из вкладки основного меню «Tools» (рис. 17):
■ FlleManager
File |
Edit |
Tools |
View Help |
||
Task Manager |
|||||
> |
Name Sy |
Calculator Paint |
Type File Folder |
Date Modifii 09.06.20191- |
|
> |
Ц tolderl |
File Folder |
09.06.2019 1- |
||
> |
folder^ |
File Folder |
09.06.20191- |
||
> |
fol deri |
File Folder |
09.06.20191- |
Рис. 17 - Вкладка «Tools» основного меню
def дег_ргосезз():
process_watcher = c.Win32_Process.watch_for("creation") while run:
try:
neW—process = process_watcher()
Рис. 18 - Метод логирования процессов
Окно с информацией о программе реализовано в отдельном классе и вызывается с помощью специализированного метода в основном классе (рис. 20).
Класс окна с информацией о программе (рис. 19):
from PyQtS import QtWidgets from multiprocessing import Process, Queue from FileManager import About from multiprocessing.connection import Client from FileManager.MailslotManager import Reader class AboutClass(QtWidgets.QMainWindow, About.Ui_About):
def __init__(self, hMailslot): super ().__init__()
def 3how_text(self):
def set_text(self, handle):
def closeEvent(self, event):
Рис. 19 - Класс окна с информацией о программе
Метод вызывающий окно с информацией о программе (рис. 20): метод создаёт экземпляр класса AboutClass и запускает окно, подключая его к серверу и отправляя сообщение о запуске.
def open_about(self):
Рис. 20 - Метод вызывающий окно с информацией о программе
Пример окна с информацией о программе (рис. 21):

Рис. 21 Окно с информацией о программе
-
1.5 Задание 5 - Добавление основного функционала
Добавить новый функционал к разработанному Файловому менеджеру:
-
1) завершение прикладного процесса, выбранного из списка;
-
2) количество страничных ошибок.
Вывод полученных данных обеспечить с возможностью обновления в реальном времени. Возможность сохранение полученных данных в файл.
Были реализованы методы получения прикладных процессов, завершения процесса, подсчета страничных ошибок и вызова окна с информацией о страничных ошибках.
Метод получения прикладных процессов (рис. 22): с помощью библиотеки psutil мы проходимся по массиву запущенных процессов и записываем их в listWidget.
def print_process(self):
for process in psutil.process_iter():
Рис. 22 - Метод получения прикладных процессов
Вызвав метод получения прикладных процессов из вкладки основного меню «View» (рис. 23) , процессы выводятся в виджет (рис. 24).
Пример вкладки меню «View» (рис. 23):

File Folder
Processes |
||
Page Error |
зе |
File Folder
File Folder
Рис 23 - Вкладка «View» основного меню
Пример списка процессов, выведенных в виджет listWidget (рис. 24):
System Idle Process а System svchost.exe fontdrvhost.exe lsass.exe Registry smss.exe svchost.exe StartMenuExperienceHost.exe csrss.exe RuntimeBroker.exe chrome.exe svchost.exe wininit.exe RuntimeBroker.exe services.exe svchost.exe svchost.exe svchost.exe svchost.exe svchost.exe svchost.exe svchost.exe svchost.exe svchost.exe Memory Compression svchost.exe WmiPrvSE.exe svchost.exe svchost.exe , , V m tr r> rr av s |
Рис. 24 - Вывод процессов в виджет
Метод завершения прикладных процессов (рис. 25): с помощью контекстного меню выбираем процесс, который хотим завершить, из списка и получаем его индекс. После чего получаем его имя и сравниваем его с запущенными процессами, если находим совпадение, то завершаем этот процесс.
def kill_process(self):
for proc in psutil.process_iter():
self.print_process()
return
Рис. 25 - Метод завершения прикладных процессов
Пример контекстного меню для завершения процесса (рис . 26):
Рис. 26 - Контекстное меню для завершения процессов
Метод подсчета страничных ошибок (рис. 27): с помощью библиотеки psutil получаем список всех процессов и получаем информацию о них, выбрав из неё количество страничных ошибок. После чего складываем это число и отправляем через мейлслот на вывод с окно с информацией о страничных ошибках (рис. 30).
def get_errors(self):
for process in self.processes:
print(process.as_dict(attrs=['memory info']))
current_string = process.as_dict(attrs=['memory_info1]) 3tring_paths = str(current_string).split(', ')
value = string_paths[2]-split('=')[1] self-page_errors += float(value)
self.open_pageErrors()
Рис. 27 - Метод подсчета страничных ошибок
Метод вызова окна с информацией о страничных ошибках (рис. 28): метод создаёт экземпляр класса PageErrorsClass, передавая ему мейлслот и запускает окно def openjpageErrors(self):
if not self-pageErrors:
Рис. 28 - Метод вызова окна с информацией о страничных ошибках
Класс окна с информацией о страничных ошибках (рис. 29):
from PyQtS import QtWidgets from multiprocessing import Process, Queue from multiprocessing.connection import Client from FileManager import PageErrors import win32file from FileManager.MailslotManager import Writer, Reader errors_dir = os.getcwd() + os.sep + 'pageErrors' if not os.path.exists(errors_dir):
class PageErrorsClass(QtWidgets.QMainWindow, PageErrors.Ui_PageErrors): def __init__(self, hMailslot):
super () .__init__() self.setupUi(self)
self .mailslot_name = "\\\\. WmailslotWmyMailslot"
def set_text(self, handle):
data = handle[1].decode('utf-8')
self.lineEdit.setlext(data)
def closeEvent(self, event):
Рис. 29 - Класс окна с информацией о страничных ошибках
Окно с информацией о страничных ошибках (рис. 30):

Рис. 30 - Окно с информацией о страничных ошибках.
1.6 Задание 6 - Тестирование разработанного ПО
Тестовые примеры для требования
№ |
Что нужно выполнить: |
Ожидаемый результат: |
Результат работы программы: |
Примечания: |
1 |
Нажатие на кнопку «Open» |
Переход в выбранную директорию |
Результат оправдал ожидание |
- |
2 |
Нажатие на кнопку «Create» |
Создание новой директории |
Результат оправдал ожидание |
- |
3 |
Нажатие на кнопку «Create File» |
Создание нового файла |
Результат оправдал ожидание |
- |
4 |
Нажатие на кнопку «Help» |
Открытие окна с информацией о программе |
Результат оправдал ожидание |
- |
5 |
Нажатие на «Copy» |
Происходит запись пути элемента в строку-буффер |
Результат оправдал ожидание |
- |
6 |
Нажатие на «Paste» |
Копируемый элемент появляется в выбранном месте |
Если буфер обмена непустой – результат оправдает ожидания. |
- |
7 |
Нажатие на «Delete» |
Удаление элемента. |
Результат оправдал ожидание |
- |
8 |
Нажатие на «Back» |
Файловый менеджер возвращается в предыдущую директорию |
Результат оправдал ожидание |
- |
2 Пример работы разработанного приложения
Задача: создать файл в папке folder1, создать вложенную папку в папке folder2 и скопировать в нее созданный файл, после чего удалить папку folder1.
1) нажимая на папку folder1 правой кнопкой мыши, выбираем
«Create File» (рис. 31);
£ FlleManager — □ X
File Edit Tools View Help
Name Size Type Date Modified
-
> □ System File Folder 09.06.2019 14:18
-
> □ft" * File Folder 12.06.201919:53
-
> □ fc Open I File Folder 12.06.2019 19:52
-
> □ fJ Create I File Folder 09.06.2019 14:22
Create File
Copy
Paste
Delete
Back
Рис. 31 - Создание файла
ФОРУМ МОЛОДЫХ УЧЕНЫХ №9(37)
-
2) нажимая на созданный файл правой кнопкой мыши, выбираем
«Copy» (рис. 32);
-
■ FlleManager — □ X
File Edit Tools View Help
Name Size lyPe
File Folder
File Folder
Q System folder!

Date Modified
09.06.201914:18
12.06.201919:53
12.06.201919:56
12.06.201919:52
09.06.201914:22
Рис. 32 - Копирование файла
-
3) нажимая на папку folder2 правой кнопкой мыши, выбираем
«Create» (рис. 33);
SI FlleManager — □ X
File Edit Tools View Help
Name |
Size |
Type |
Date Modified |
> Q System |
File Folder |
09.06201914:18 |
|
v Q folderl |
File Folder |
12.06201919:56 |
|
J new |
_file |
0 байты File |
12.06201919:56 |
fold |
Create |
. File Folder |
12.06.201919:52 |
L fold |
File Folder |
09.06.2019 14:22 |
Create File
Copy Paste Delete Back
Рис. 33 - Создание вложенной папки
-
4) нажимая на созданную папку правой кнопкой мыши, выбираем «Paste» (рис. 34);
■ FlleManager — □ X
File Edit Tools View Help
Name Size Type Date Modified > □ System File Folder 09.06.2019 14:18 V Q folder! File Folder 12.06.2019 19:56 П newjile 0 байты File 12.06.201919:56 V 3 folder2 File Folder 12.06.201919:52 |
|||
folder |
°Pen File Folder 09.06.2019 14:22 Create File Copy |
||
Paste |
|||
Delete Back |
|||
Рис. 34 - вставка файла
-
5) нажимая на папку folder1 правой кнопкой мыши, выбираем «Delete» (рис. 35).
Рис. 35 - Удаление папки folder1
Результат работы программы (рис. 36):
■1 FlleManager — □ X
File Edit Tools View Help
Name > Д System |
Size |
Type File Folder |
Date Modified 09.06.2019 14:18 |
||
v folder2 |
File Folder |
12.06.2019 20:04 |
|||
v |~ii new_folder ] new_file > ■ folderB |
0 байты |
File Folder File File Folder |
12.06.2019 20:04 12.06.2019 20:05 09.06.2019 14:22 |
Рис. 36 Результат работы
3 Заключение
В процессе выполнения данной работы мы ознакомились с методами создания многопоточного приложения с графическим интерфейсом на языке Python и разработали файловый менеджер, который упрощает работу с файлами для пользователя.
Список литературы Разработка файлового менеджера на языке Python
- Python 3.7.3 documentation [Электронный ресурс] Режим доступа: https://docs.python.org/3.7
- Qt Documentation [Электронный ресурс] Режим доступа: https://doc.qt.io
- WIM Cookbook [Электронный ресурс] Режим доступа: http://timgolden.me.uk/python/wmi/tutorial.html