Пока что наша программа состоит из экземпляров классов, реализованных в предыдущем разделе, которые сохранены в файле хранилища. В качестве хранилища она делает достаточно, но для доступа к содержимому и работы с ним нам потребуется запускать другие сценарии или вводить программный код в интерактивной оболочке. Улучшить ситуацию достаточно просто: необходимо написать универсальную программу, которая будет взаимодействовать с пользователем либо с помощью окна консоли, либо с помощью графического интерфейса.
Интерфейс командной строки к хранилищу
Начнем с наиболее простого варианта. В самом простом виде интерфейс к базе данных должен давать пользователям возможность вводить ключи и значения в окне консоли (вместо того чтобы писать программный код на языке Python). Сценарий в примере 1.21 реализует простейший цикл интерактивных взаимодействий, позволяя пользователю запрашивать объекты, имеющиеся в хранилище.
Пример 1.21. PP4E\Preview\peopleinteract_query.py
# интерактивные запросы import shelve
fieldnames = (‘name’, ‘age’, ‘job’, ‘pay’) maxfield = max(len(f) for f in fieldnames) db = shelve.open(‘class-shelve’)
while True:
key = input(‘\nKey? => ‘) # ключ или пустая строка, возбуждает исключение # при вводе EOF
if not key: break try:
record = db[key] # извлечь запись по ключу и вывести except:
print(‘No such key “%s”!’ % key) else:
for field in fieldnames: print(field.ljust(maxfield), ‘=>’, getattr(record, field))
Для извлечения значений атрибутов в этом сценарии используется встроенная функция getattr, а для форматирования вывода используется строковый метод ljust, выравнивающий строку по левому краю (значение maxfield, порожденное выражением-генератором, представляет длину наибольшего имени поля). После запуска сценария он входит в цикл, предлагает пользователю ввести ключ (со стандартного потока ввода, который обычно соответствует окну консоли) и отображает извлеченную запись поле за полем. Ввод пустой строки завершает сеанс работы со сценарием. Предположим, хранилище находится в том же состоянии, в каком мы его оставили ближе к концу предыдущего раздела:
…\PP4E\Preview> dump_db_classes.py bob =>
Bob Smith 30000 sue =>
Sue Jones 50000.0 tom =>
Tom Doe 65000.0
Smith
Doe
Мы сможем использовать наш новый сценарий для запроса объектов из базы данных в интерактивном режиме:
…\PP4E\Preview> peopleinteract_query.py
Key? => sue
name => Sue Jones
age => 45
job => hardware
pay => 50000.0
Key? => nobody
No such key “nobody”!
Key? =>
Сценарий в примере 1.22 является следующим шагом к созданию интерфейса, позволяющим вносить изменения в интерактивном режиме. Для заданного ключа он позволяет ввести значения для каждого из полей и либо изменяет существующую запись, либо создает новую, после чего сохраняет ее с указанным ключом.
Пример 1.22. PP4E\Preview\peopleinteract_update.py
# интерактивные изменения import shelve
from person import Person
fieldnames = (‘name’, ‘age’, ‘job’, ‘pay’)
db = shelve.open(‘class-shelve’) while True:
key = input(‘\nKey? => ‘) if not key: break if key in db:
record = db[key] # изменить существующую
else: # или создать новую запись
record = Person(name=’?’, age=’?’) # для eval: строки в кавычках for field in fieldnames:
currval = getattr(record, field)
newtext = input(‘\t[%s]=%s\n\t\tnew?=>’ % (field, currval)) if newtext:
setattr(record, field, eval(newtext)) db[key] = record
db.close()
Обратите внимание, что для преобразования введенных значений в этом сценарии используется функция eval (это позволяет вводить любые объекты Python, но это означает, что строки при вводе должны заключаться в кавычки). Функция setattr присваивает значение атрибуту, имя которого задается строкой. Этот сценарий позволит добавлять или изменять любое количество записей — чтобы сохранить прежнее значение поля в записи, достаточно просто нажать клавишу Enter в ответ на просьбу ввести новое значение:
Key? => tom
[name]=Tom Doe new?=> [age]=50
new?=>56
[job]=None
new?=>’mgr’ [pay]=65000.0
new?=>90000
Key? => nobody
[name]=?
new?=>’John Doh’ [age]=?
new?=>55
[job]=None
new?=>
[pay]=0
new?=>None
Key? =>
Этот сценарий все еще очень прост (в нем, например, не предусмотрена обработка ошибок), но пользоваться им гораздо удобнее, чем вручную открывать и вносить изменения в хранилище в интерактивной оболочке Python, особенно для тех, кто не занимается программированием. Запустим сценарий peopleinteract_query.py, чтобы проверить изменения, которые мы внесли (если кому-то такой подход покажется утомительным, он сможет объединить оба сценария в один, ценой дополнительного программного кода и повышения сложности для пользователя):
Key? => tom name => Tom Doe age => 56 job => mgr pay => 90000
Key? => nobody name => John Doh age => 55 job => None pay => None
Key? =>
Использованная литература:
Марк Лутц — Программирование на Python, 4-е издание, I том, 2011