Я пишу скрипт на Python, который использует данные сомнительного качества. Данные хранятся в базе данных SQLite .
Я бы хотел компактный способ указать ограничения на данные. Ограничения бывают двух типов:
- Ошибки данных - будет выдано сообщение об ошибке.
- "Столбец A должен быть целым числом в диапазоне 0-10"
- «Столбец B должен быть непустой строкой» и т. Д.
- Предупреждения о качестве данных - " Вы уверены, что это правильно ?" Будет выпущено предупреждение. Ограничения будут такими вещами, как
- "предупредить, если для столбца C установлено значение по умолчанию 0" - вы уверены, что машинистка не пропустила запись?
- "предупредить, если число в столбце D необычно велико (> 1000)".
В идеале я бы хотел бы , чтобы выразить свои ограничения в удобочитаемом формате, например:
'kV' MUST BE float IN RANGE 0-10
'Rating' SHOULD NOT BE DEFAULT 1.0
'Description' SHOULD NOT BE DEFAULT ""
... но я улучшу свой текущий подход (ниже). Я был бы рад принять решение, которое включает в себя применение ограничений либо в Python, либо в схеме SQLite.
Вот что я сейчас использую:
def is_number_in_range(number, expected_type, lower, upper):
if type(number) != expected_type:
return "not an %s" % expected_type
elif ((number < lower) or (number > upper)):
return "%s out of range [%i-%i]." % (expected_type, upper, lower)
else:
return "OK"
def not_default (value, expected_type, default_value):
if type(value) != expected_type:
return "not an %s" % expected_type
elif value == default_value:
return "default value of %s - make sure this is what you want." % default_value
else:
return "OK"
def Check_Cable_Lib(db_conn):
res = db_conn.execute("SELECT * FROM Lib_Cable LIMIT 1")
constraints = (
('kV', lambda x: is_number_in_range(x, float, 0, 1000) ),
('kA1', lambda x: is_number_in_range (x, float, 0, 10) ),
('kA1', lambda x: not_default(x, float, 1.0))
)
for cable_type in res:
for constraint in constraints:
constraint_variable = constraint[0]
constraint_data = cable_type[constraint_variable]
constraint_function = constraint[1]
validation_message = constraint_function(constraint_data)
print ("%(constraint_variable)s = %(constraint_data)s : %(validation_message)s" % locals())
stage1_db_path = "stage1.sqlite3";
db_conn = sqlite3.connect(stage1_db_path)
db_conn.row_factory = sqlite3.Row
Check_Cable_Lib(db_conn)
Пример вывода:
kV = 11.0 : OK
kA1 = 1.0 : OK
kA1 = 1.0 : default value of 1.0 - make sure this is what you want.
РЕДАКТИРОВАТЬ: Я знаю, что невежливо явно проверять типы в Python. Однако ради кода, который использует данные, мне нужно убедиться, что SQLite не хранил неожиданные вещи в столбцах («привет мир» в столбце INT и т. Д.) Помните, что данные имеют сомнительное качество, и SQLite с радостью поместите любой тип данных в любой столбец. Улавливание этих типов ошибок при вводе данных является одной из целей этого кода.