我使用python和sqlite3来维护一个数据库,在我插入任何东西之前,我需要对数据执行验证检查,这样我就知道,即使非常宽容的数据库会接受垃圾输入,但实际发生的并不是垃圾输入。
为了实现这一点,一个表示数据库记录且其字段与列的1:1匹配的类将在同一模块中具有类似的方法:

def validate_path(path):
   if path == None:
      return False
   if len(path) < 5:
      return False
   if not re.search("^/[a-zA-Z0-9_/]+/$", path):
      return False
   else:
      return True

def validate_server(server):
   if server == None:
      return False
   if len(server) < 3:
      return False
   if not re.search("^[a-z][a-zA-Z0-9]+$", server):
      return False
   else:
      return True

def validate_name(name):
   if name == None:
      return False
   if len(name) < 3:
      return False
   if not re.search("^[a-z][a-z_]+$", name):
      return False
   else:
      return True

在实现我的目标时,这很容易理解,但我觉得它效率低下/if语句太多/是解决问题的非常“初学者”的方法。
在我的课上,我会有一个方法,比如:
   def validate(self):
      if validate_name(self.name) == False or \
         validate_server(self.home_file_server) == False or \
         validate_path(self.home_path) == False or \
         validate_server(self.web_file_server) == False or \
         validate_path(self.web_path) == False:
         return False
      else:
         return True

所以在运行insert命令之前,我运行:
if dbrecord.validate() == False:
   # do not insert
else:
   # insert

各个验证方法保持在模块级(不在类中),因为我在计算客户端脚本中的用户输入时使用相同的方法。例如:
while True:
  home_path = raw_input("Home directory path: ")

  if AccountTypeManager.validate_path(home_path) == False:
     print "Invalid home directory path"
     logger.debug("User input home directory path {0} deemed invalid".format(home_path))
     continue

  logger.debug("User input home directory path {0} accepted as valid input.".format(home_path))
  break

我在这两个方法中都进行了验证(除了客户端脚本输入),因为该方法可能在其他地方重新使用,或者以不接受客户端输入的其他方式使用,并且不考虑数据来自何处,在进入之前必须对其进行检查。
我主要关心的是可维护性和可读性。我希望避免使用外部模块,因为很可能我的继任者没有python经验,像我一样从头开始。我想以一种“pythonic”的方式完成上面的工作,这种方式在非python背景下也很容易实现。
我还听说在python中,最好使用异常进行验证,而不是true/false值。这是真的吗?

最佳答案

我看到你的代码有些冗余。我认为可能有帮助的是:
在dict中存储匹配的模式(按照此路线,还必须存储长度)
将验证功能合并为一个。
将if语句合并到pythonicall语句中。
考虑在validate函数中使用和查找一个false
例如。

pattern_dict = {'server' : '^[a-z][a-zA-Z0-9]+$',...}

def aux_validate(my_input,input_type):
    return all([my_input is not None, re.search(pattern_dict[input_type],my_input),...])


def validate(self):
    validator = True
    for my_input,input_type in self.inputs:
        validator = validator and aux_validate(my_input,input_type)
    return validator

如果你想得到一点幻想,你可以考虑使用一个列表理解与验证和返回所有,即。
return all([aux_validate(my_input,input_type) for my_input,input_type in self.inputs])

最后,这可能会被认为是自以为是的,您最好检查http://codereview.stackexchange.com

关于python - 使用Python进行有效的数据验证,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21372753/

10-16 17:36
查看更多