УДК 004.5
Глебов С.И. студент 3 курса
факультет «Информационных систем и технологий»
Ивлиева И.А. студент 3 курса
факультет «Информационных систем и технологий» Поволжский государственный университет телекоммуникаций и информатики научный руководитель: Часов Е.А.
старший преподаватель Россия, г. Самара
РАЗРАБОТКА ФАЙЛОВОГО МЕНЕДЖЕРА НА ЯЗЫКЕ PYTHON
Аннотация: Статья посвящена разработке файлового менеджера на языке Python. При разработке выполняются поставленные задачи. При выполнении каждой задачи подробно расписывается, что было добавлено и как это работает.
Ключевые слова: Python, pytq5, программирование, графический интерфейс, буфер
Glebov S.I. student
3 course, faculty «Information Systems and Technologies» Volga State University of Telecommunications and Informatics
Russia, Samara Ivlieva I.A. Student
3 course, faculty «Information Systems and Technologies» Volga State University of Telecommunications and Informatics
Russia, Samara Scientific director: Chasov E.A.
Senior Lecturer PYTHON FILE MANAGER DEVELOPMENT Annotation: 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.
Keywords: Python, pytq5, programming, graphical interface, buffer
Введение
Актуальность: Файловый менеджер - самый удобный, на данный момент, способ взаимодействия с файлами. Он позволяет за довольно короткое время выполнить множество операций, и что самое главное, за счёт реализации графического интерфейса рядовому пользователю всё становится интуитивно понятно.
Объект исследования: Файловый менеджер. Предмет исследования: Операционная система.
Цель: закрепление и углубление теоретических знаний в области современных операционных систем.
Задачи:
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).
Рис. 2 - Графический интерфейс программы
1.3 ЗАДАНИЕ 3 - РАЗРАБОТКА ПО
Создается корневая папка как среда работы Файлового менеджера. Создается папка «System», содержит все необходимые файлы для работы файлового менеджера. Так же создаются рабочие папки. Сделать основное и контекстное меню.
Были созданы каталоги System и несколько пользовательских директорий, в которых находятся, соответственно, файлы приложения и пользовательские файлы.
Были реализованы методы перехода в директорию (рис. 3), создания файла (рис. 6) и папки (рис. 5), копирования (рис. 7), удаления (рис. 9), вставки (рис. 8) и возврата в предыдущую директорию (рис. 4).
Метод перехода в директорию (рис. 3): в данном методе мы получаем индекс папки из списка, которую мы хотим перейти, получаем её путь и отображаем в TreeView эту директорию.
index = sel:,treeView.currentIndex()
self . treeView. setRoot Index (sel: . mcdel,. index (path))
Рис. 3 - Метод перехода в директорию
Метод возврата в предыдущую директорию (рис. 4): в данном методе мы делим текущий путь по разделителю и удаляем последний элемент, после чего объединяем оставшиеся элементы в строку и отображаем директорию, находящуюся по этому пути, в Tree View
self ''. treeView.setRootlndexfself ^mcdel.index(new_path))
Рис. 4 - Метод возврата в предыдущую директорию
Метод создания папки (рис. 5): в данном методе мы получаем индекс папки, в которой мы хотим создать папку, из списка. После чего получаем её путь и добавляем к её пути название новой папки (если такая папка уже существует, то добавляется индекс по числу папок с таким именем).
"new^^th^ path^ ' \\nev_Folder1 + str (path_index)
Рис. 5 - Метод создания папки
Метод создания файла (рис. 6): в данном методе мы получаем индекс папки, в которой мы хотим создать файл, из списка. После чего получаем её путь и добавляем к её пути название нового файла (если такой файл уже существует, то добавляется индекс по числу файлов с таким именем).
Рис 6 - Метод создания файла
Метод копирования (рис. 7): в данном методе мы получаем индекс элемента, который мы хотим скопировать (папка или файл), из списка. После чего получаем его путь и копируем его в строку-буфер.
index = self.treeView.currentIndex() path = self.mcdel.fileFath(index)
Рис. 7 - Метод копирования
Метод вставки (рис. 8): в данном методе мы получаем индекс папки, в которую хотим вставить скопированный элемент, из списка. После чего копируем элемент из пути в строке-буфере в путь выбранной папки.
index = self". treeView. cur rent Index () path = sel:.mcdel.fileFath(index)
3hutil.copy(3elz,buffer_stringF path)
Рис. 8 - Метод вставки
Метод удаления (рис. 9): в данном методе мы получаем индекс элемента, который хотим удалить (папка или файл), из списка. После чего получаем его путь и удаляем элемент по данному пути.
i ndex = self",tree View.currentI ndex () path = sel:.mcdel.fileFath(index)
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 = QtW idget з.QMeгш ()
ohange_root_path = QtWidgets.Qiction('Open', menu) menu, addiction(change_root_path) create_fcider = Qtiïidgets.Qiction('Create', menu) menu.addiction(create_fcider)
create_file = QtWidgets.Qictionf'Create File', menu) menu.addiction(create_file)
copy_folder = QtWidgets.Qiction{ 'Copy ' , menu) menu.addiction(copy_folder)
paste_folder = QtWidgets.Qictionf'Paste1 , menu) menu,addiction(paste_folder)
delete_fcider = Qtiïidgets.Qiction('Delete', menu)
menu,addiction(delete_fcider)
back_path = QtWidgets.Qiction('Baci1, menu)
menu,addiction(back_path)
action = menu.exec_(event,globalPos{))
if action == create_folder:
self,create_dir() elif action == copy_fclder:
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()
if event,type() == QtCore.QEvent.ContextMenu and obj is self,listWidget menu = Qtïiidgets.QMenu{)
terminate_button = QtWidgets.Qictioni'Terminate', menu) menu,addiction(terminate_button) action = menu.exec_(event,globalPos() )| if action == terminate_button: self,till_process()
T*sfciirri Я1ЮРГ iFx^mnl рВтуп. . pvpntFi 1 tpr fnhi . pvpnt I
Рис. 10 - Метод EventFilter
Пример контекстного меню (рис. 11):
FlleManager File Edit Tools View Help
Name Size Type Date Modified
> System File Folder 09.06.2019 14:13
> folderl File Folder 09.06.201914:22
> folde -— Open Create Create File Copy Paste Delete Back File Folder 09.06.201914:22
> foldt File Folder 09.06.201914:22
Рис. 11 - Контекстное меню
Создаются несколько меню с кнопками для них, к которым привязываются действия (рис. 12):
# шели
mainMenu = fell.menuBar() fileMenu = mainMenu.addMenu('File') open_button = 2tHidgets.QAction( 'Open' , fileMenu) fileMenu,addiction(open_button)
close_button = QtHidgets.QAction('Close', fileMenu) с 1 oae_but t on.t r i gge red. conne et (qApp. qui t ) fileMenu.addiction(olose_button)
edi tMenu = mai nMenu.addMenu(1E di t ')
ohange_log_name_button = QtWidgets.QActionf'Change Log Name', editMenu) change_log_name_button, triggered, connect (self.open_ohange_log_name) edi tMenu,a ddAct i on(cha nge_log_name_bu11 on)
toolsMenu = mainMenu.addMenu('Tools')
taslr_manager_button = QtWidgeta.QActionf'Task Manager', toolsMenu) tas k_ma na ge r_but t on.t r i gge red.conne ct(self.open_tas t_ma nager) too1sMenu.addAct i on(t a s k_ma nage r_but ton)
calculator_button = QtHidgets.QAction('Calculator', toolsMenu) calculator_button,triggered.connect(self.open_calculator) too1sMenu.addAct i on(ca1cula tor_but ton) paint_button = QtHidgets.QAction('Paint', toolsMenu) paint_button.triggered.connect(3elf.open_paint) toolsMenu.addiction(paint_button)
viewMenu = mainMenu.addMenu('View')
processes_button = QtWidgets.QAction('Processes', viewMenu) processes_button,triggered.connect(self,print_process) viewMenu.a ddAct i on(prо ce s se s_button)
pageError_button = QtWidgets.QAction('Page Error', viewMenu) pageError_button.triggered.connect(self.get_errors) vi ewMenu.a ddAct i on(pa geE rro r_but ton)
helpMenu = mainMenu.addMenu('Help') abcut_button = QtHidgets.QAction('About', helpMenu) about_button,triggered,connect(3elf,open_about) helpMenu.addiction(abcut_button)
Рис. 12 - Реализация основного меню
Пример основного меню (рис. 13):
Рис. 13 - Основное меню
1.4 ЗАДАНИЕ 4 - ОБЕСПЕЧЕНИЕ МИНИМАЛЬНОГО ФУНКЦИОНАЛА
С помощью приложения обеспечить возможность создания нового процесса (всплывающее окно), которое будет в дальнейшем отображать информацию основного функционала (или части его). Позволить через приложение запуск встроенных системных утилит ОС. Сохранение протокола запущенных в период работы Файлового менеджера процессов в текстовом файле (имя процесса и время старта). Имя файла задается пользователем.
Были реализованы такие методы как: вызов системных утилит (Диспетчер задач, калькулятор и paint), логирование процессов, запущенных во время работы приложения и окно c информацией о программе.
Метод открытия диспетчера задач (рис. 14): открываем диспетчер задач, с помощью библиотеки os.
оэ. system (г'С : \Windows\system32\tasiir.gr.exe1 )
Рис. 14 - Метод открытия диспетчера задач
Метод открытия калькулятора (рис. 15): открываем калькулятор, с помощью библиотеки os.
os.system(г'С:\Windows\system32\calc.exe1)
Рис. 15 - Метод открытия калькулятора
os.
Метод открытия paint (рис. 16): открываем paint, с помощью библиотеки
оэ.system(г'С:\Windows\sjstem32\E.spaint. ехе1)
Рис. 16 - Метод открытия paint
Эти 3 метода вызываются из вкладки основного меню «Tools» (рис. 17):
■ FlleManaçjer
File Edit Tools View Help Task Manager Calculator Paint
foflïFT folderZ folded
Type
File Folder File Folder File Folder File Folder
Date M od if ii 09,06,2019 109,06,2019 1. 09,06,2019 109,06,2019 1-
Рис. 17 - Вкладка «Tools» основного меню
Метод логирования процессов (рис. 18): метод запускается вместе с программой в отдельном потоке и просматривает запускаемые и закрываемые программы и записывает изменения в файл log.txt.
def get_process():
pythonccm,Colnitialize() с = wl.HHI ()
process_watcher = с.Win32_Proсеss.watch_for("creation") while run: try:
new_process = process_watcher()
file.write(str(new_process.Name) + " " + new_process.CreationDate + '\n') file,flush() except ValueError: print("Error") file,close()
thread = threading.Thread(target=get_process) thread.start()
Рис. 18 - Метод логирования процессов
Окно с информацией о программе реализовано в отдельном классе и вызывается с помощью специализированного метода в основном классе (рис. 20).
Класс окна с информацией о программе (рис. 19):
class About 01a s s (QtHidge t э. QMainWindow, About. Ui_About) :
self.reader = Reader(3elf.mailslot_name, self.hMail3lot, self.set_text)
Рис. 19 - Класс окна с информацией о программе
Метод вызывающий окно с информацией о программе (рис. 20): метод создаёт экземпляр класса AboutClass и запускает окно, подключая его к серверу и отправляя сообщение о запуске.
writer = Hriter(зе1:,abcut_mailslot_nameF self,write_about) self.about = AboutC'lass (self. about_mailslot)
Рис. 20 - Метод вызывающий окно с информацией о программе Пример окна с информацией о программе (рис. 21):
Рис. 21 Окно с информацией о программе
1.5 ЗАДАНИЕ 5 - ДОБАВЛЕНИЕ ОСНОВНОГО ФУНКЦИОНАЛА
Добавить новый функционал к разработанному Файловому менеджеру:
1) завершение прикладного процесса, выбранного из списка;
2) количество страничных ошибок.
Вывод полученных данных обеспечить с возможностью обновления в реальном времени. Возможность сохранение полученных данных в файл.
Были реализованы методы получения прикладных процессов, завершения процесса, подсчета страничных ошибок и вызова окна с информацией о страничных ошибках.
Метод получения прикладных процессов (рис. 22): с помощью библиотеки рБиШ мы проходимся по массиву запущенных процессов и записываем их в listWidget.
sel:.listWidget!addltemístr (procesa.ñame()))
Рис. 22 - Метод получения прикладных процессов
Вызвав метод получения прикладных процессов из вкладки основного меню «View» (рис. 23) , процессы выводятся в виджет (рис. 24). Пример вкладки меню «View» (рис. 23):
FlleManager
File Edit Tools View Help
Processes
Name System folderl Page Error не
> > File Folder File Folder
> folder? File Folder
Рис 23 - Вкладка «View» основного меню Пример списка процессов, выведенных в виджет listWidget (рис. 24):
□ X
System Idle Process л
System
svchost.exe
fontdrvhost.exe
lsass.exe
Registry
smss.exe
svchost.exe
StartMenuExperienceHost.exe csrss.exe
Ru nt i m eBroker, ex e
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
ova
Рис. 24 - Вывод процессов в виджет
Метод завершения прикладных процессов (рис. 25): с помощью контекстного меню выбираем процесс, который хотим завершить, из списка и получаем его индекс. После чего получаем его имя и сравниваем его с запущенными процессами, если находим совпадение, то завершаем этот процесс.
index = sel:.listWidge t.currentIndex() item = self.listiiidget.mcdel().data(index)
for proc in psutil.process_iter():
Рис. 25 - Метод завершения прикладных процессов Пример контекстного меню для завершения процесса (рис . 26):
svchost.exe svchost.exe svchost.exe
SkypeA.....
backgrc svchost.exe svchost.exe svchost.exe svchost.exe svchost.exe svchost.exe
Рис. 26 - Контекстное меню для завершения процессов
Метод подсчета страничных ошибок (рис. 27): с помощью библиотеки psutil получаем список всех процессов и получаем информацию о них, выбрав из неё количество страничных ошибок. После чего складываем это число и отправляем через мейлслот на вывод с окно с информацией о страничных ошибках (рис. 30).
Terminate
print (process. as_dict (attr3=['memor"j_infc ' ]))
current_string = process.as_dict(attrs=['memor7_info']) writer = Hriter(3eli.inailslot_nameF sell.write_errors)
Рис. 27 - Метод подсчета страничных ошибок
Метод вызова окна с информацией о страничных ошибках (рис. 28): метод создаёт экземпляр класса PageErrorsClass, передавая ему мейлслот и запускает окно
self "pageErrors = PageErrorsClass(self.mailslot)
Рис. 28 - Метод вызова окна с информацией о страничных ошибках Класс окна с информацией о страничных ошибках (рис. 29):
from PyQtS import QtWidgets from multiprocessing ijiport Process, Queue from multiprocessing.connection rmport Client from FileManager import FageErrors Import win32file
from FileManager.MailslotManager Import Writer, Reader
errors_dir = os.getcwd() + os.sep + 'pageErrors'
if not os.path.exists{errors_dir):
os,mtdir(errors_dir)
file = open(errors_dir + os.sep + 'pageErrors.txt1, 'w')
class PageErrorsClass(StWidgets.QMainiiindow, PageErrors.Ui_FageErrors):
def _init_(3elf, hMailslot):
super()._init_()
self.setupUi(sell)
self , mailslot_name = "WW , Wi.ailslotWmjMailslot" self.hMailslot = hMailslot self.conn = None
self.reader = Reader(3elf.mailslot_name, hMailslot, self.set_text) self.reader.start()
def set_text(3elf, handle):
data = handle[1].decode('utf-6')
self,lineEdit.setText(data)
file.write('Page Errors Count = ' + data)
file.flush()
def closeEvent(3el:, event):
self, reader,, join(u . 0000001) event,accept()
Рис. 29 - Класс окна с информацией о страничных ошибках Окно с информацией о страничных ошибках (рис. 30):
IH РадеЕгго
□
X
162396206,0
ГГ
Рис. 30 - Окно с информацией о страничных ошибках.
1.6 ЗАДАНИЕ 6 - ТЕСТИРОВАНИЕ РАЗРАБОТАННОГО ПО
Тестовые примеры для требования
№ Что нужно выполнить: Ожидаемый результат: Результат работы программы: Примечания:
1 Нажатие на кнопку «Open» Переход в выбранную директорию Результат оправдал ожидание
2 Нажатие на кнопку «Create» Создание новой директории Результат оправдал ожидание
3 Нажатие на кнопку «Create File» Создание нового файла Результат оправдал ожидание
4 Нажатие на кнопку «Help» Открытие окна с информацией о программе Результат оправдал ожидание
5 Нажатие на «Copy» Происходит запись пути элемента в строку-буффер Результат оправдал ожидание
6 Нажатие на «Paste» Копируемый элемент появляется в выбранном месте Если буфер обмена непустой -результат оправдает ожидания.
7 Нажатие на «Delete» Удаление элемента. Результат оправдал ожидание
8 Нажатие на «Back» Файловый менеджер возвращается в предыдущую директорию Результат оправдал ожидание
2 Пример работы разработанного приложения
Задача: создать файл в папке folder 1, создать вложенную папку в папке folder2 и скопировать в нее созданный файл, после чего удалить папку folder1.
1) нажимая на папку folder 1 правой кнопкой мыши, выбираем «Create File» (рис. 31);
Рис. 31 - Создание файла
2) нажимая на созданный файл правой кнопкой мыши, выбираем «Copy» (рис. 32);
Рис. 32 - Копирование файла
3) нажимая на папку folder2 правой кнопкой мыши, выбираем «Create» (рис. 33);
Рис. 33 - Создание вложенной папки
4) нажимая на созданную папку правой кнопкой мыши, выбираем «Paste» (рис. 34);
Рис. 34 - вставка файла
5) нажимая на папку folder 1 правой кнопкой мыши, выбираем «Delete» (рис. 35).
Рис. 35 - Удаление папки folder1
Результат работы программы (рис. 36):
Рис. 36 Результат работы
3 Заключение
В процессе выполнения данной работы мы ознакомились с методами создания многопоточного приложения с графическим интерфейсом на языке Python и разработали файловый менеджер, который упрощает работу с файлами для пользователя.
Использованные источники:
1. Python 3.7.3 documentation [Электронный ресурс] Режим доступа: https://docs.python.org/3.7/
2. Qt Documentation [Электронный ресурс] Режим доступа: https://doc.qt.io/
3. WIM Cookbook [Электронный ресурс] Режим доступа: http://timgolden.me.uk/python/wmi/tutorial.html