Разработка файлового менеджера на языке Python
Автор: Глебов С.И., Ивлиева И.А.
Журнал: Форум молодых ученых @forum-nauka
Статья в выпуске: 9 (37), 2019 года.
Бесплатный доступ
Статья посвящена разработке файлового менеджера на языке Python. При разработке выполняются поставленные задачи. При выполнении каждой задачи подробно расписывается, что было добавлено и как это работает.
Программирование, графический интерфейс, буфер
Короткий адрес: https://sciup.org/140287036
IDR: 140287036 | УДК: 004.5
Python file manager development
The article is devoted to the development of a file manager in Python. We performed some assigned tasks. During each task, it is written in detail what was added and how it works.
Текст научной статьи Разработка файлового менеджера на языке 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