Вот функция save_document()
, это опрашивает нажатие Extract PDF
кнопка во внешней программе и сохраняет файл PDF в формате tmp на USB-накопитель.
import time
import os
import shutil
def save_document():
print("nnPreparing to save the document...", end = "r")
TEMP_PDF_DIR = "C:/Users/TUN/tp3/workspace/tmp" # temporary pdfs are stored in this directory
while not os.listdir(TEMP_PDF_DIR): # wait until the "Extract PDF" button is pressed and a file will be created in directory TEMP_PDF_DIR
time.sleep(0.5)
continue
file_path = "C:/Users/TUN/tp3/workspace/tmp" + "/" + os.listdir(TEMP_PDF_DIR)[0]
shutil.move(file_path, find_drive_id()) # move the file in the USB drive directory
print("Document PDF was saved successfully.")
И find_drive()
функция, которая ищет запоминающее устройство с заданным серийный номер и возвращает его путь (буква пути, например D :, F: и т. д.)
import wmi
def find_drive_id():
local_machine_connection = wmi.WMI()
DRIVE_SERIAL_NUMBER = "88809AB5" # serial number is like an identifier for a storage device determined by system
'''.Win32.LogicalDisk returns list of wmi_object objects, which include information
about all storage devices and discs (C:, D:)'''
for storage_device in local_machine_connection.Win32_LogicalDisk():
if storage_device.VolumeSerialNumber == DRIVE_SERIAL_NUMBER:
return storage_device.DeviceID
return False
Есть ли лучший способ сохранить только что созданный временный файл PDF?
Кроме того, меня беспокоит цикл опроса … Я считаю, что есть более элегантный подход.
1 ответ
Общие комментарии
Лично опрос кажется нормальным, стандартный способ сделать это — использовать watchdog
. Я просто укажу на некоторые моменты, которые мне кажутся странными в вашем коде.
imports
Распространенный способ в Python — разделить импорт на три части: встроенные модули, модули сообщества и локальные. Так что это
import time
import os
import shutil
Действительно должно быть это
import time
import os
import shutil
Потому что time
, os
а также shutil
все живут в стандартная библиотека.
descriptive function names
Называть это сложно, но очень важно хорошо подумать о том, как вы называете вещи; особенно функции, классы и модули. Основная причина, почему
save_document()
: а также find_drive_id()
Плохие имена потому, что они не делают то, что говорят. Сохранить документ не сохраняет документ, а перемещает уже сохранено документ в другую папку. сходным образом find_drive_id
не находит идентификатор диска, но возвращает путь к диску.
hardcoded paths
Это сделка 2 по цене 1. Первые пути лучше обрабатывать с помощью pathlib
модуль (опять же в стандартной библиотеке). Кроме того, мы используем этот путь несколько раз, поэтому он должен быть извлечен в его собственную глобальную константу.
import pathlib
DIRECTORY_TO_WATCH = pathlib.PureWindowsPath("c:/Users/TUN/tp3/workspace/tmp")
сходным образом DRIVE_SERIAL_NUMBER = "88809AB5"
вероятно, тоже должна быть глобальной константой.
Тройные кавычки обычно зарезервированы для строки документации. Вдобавок это
'''.Win32.LogicalDisk returns list of wmi_object objects, which include information
about all storage devices and discs (C:, D:)'''
является скорее комментарием, чем цитатой, и может быть преобразован в #
. Кроме того, вы должны добавить строки документации, объясняющие, что делает каждая функция.
Это действительно мелочь, но мы можем написать
for storage_device in local_machine_connection.Win32_LogicalDisk():
if storage_device.VolumeSerialNumber == DRIVE_SERIAL_NUMBER:
return storage_device.DeviceID
else:
return False
Что я нахожу более понятным для чтения. Если мы не сломаемся или не вернемся в for loop
в else
оговорка срабатывает. Вы также можете подумать о else
в качестве then
.
Поместите те части вашего кода, которые требуют выполнения, за if __name__ == "__main__":
сторожить. Таким образом, вы можете импортировать этот модуль python из других мест, если хотите, а защита предотвращает случайный запуск основного кода при каждом импорте.
Пример кода
Вот макет того, как реализация сторожевого пса could
Смотреть. Обратите внимание, что я работаю в Linux и у меня нет возможности проверить детали, если все реализовано правильно. Однако это должно быть хорошей отправной точкой =)
import time
import pathlib
import shutil
import wmi
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
DIRECTORY_TO_WATCH = pathlib.PureWindowsPath("c:/Users/TUN/tp3/workspace/tmp")
# serial number is like an identifier for a storage device determined by system
DRIVE_SERIAL_NUMBER = "88809AB5"
SLEEP_TIME = 5
class Watcher:
DIRECTORY_TO_WATCH = DIRECTORY_TO_WATCH
SLEEP_TIME = SLEEP_TIME
def __init__(self):
self.observer = Observer()
def run(self):
event_handler = Handler()
self.observer.schedule(event_handler, self.DIRECTORY_TO_WATCH, recursive=True)
self.observer.start()
try:
while True:
time.sleep(self.SLEEP_TIME)
except:
self.observer.stop()
print("Error")
self.observer.join()
class Handler(FileSystemEventHandler):
@staticmethod
def on_any_event(event):
if event.is_directory:
return None
elif event.event_type == "created":
# Take any action here when a file is first created.
# move the file in the USB drive directory
file_path = pathlib.PureWindowsPath(event.src_path)
shutil.move(file_path, get_usb_path())
print("Document PDF was saved successfully.")
def get_usb_path():
local_machine_connection = wmi.WMI()
# Win32.LogicalDisk returns list of wmi_object objects, which include
# information about all storage devices and discs (C:, D:)
for storage_device in local_machine_connection.Win32_LogicalDisk():
if storage_device.VolumeSerialNumber == DRIVE_SERIAL_NUMBER:
return storage_device.DeviceID
else:
return False
if __name__ == "__main__":
w = Watcher()
w.run()