Pythonic验证用户输入的方法

时间:2017-01-13 17:57:01

标签: python function try-except

是否有任何pythonic方式来处理错误的用户输入?我正在创建一个模块来帮助人们处理文件,我有重命名,移动,basepath等功能。例如:

def move(file_path):
    # do something and return

我想知道如何处理异常(例如,如果我将代码包装在try-except块中);

def move(file_path):
    try:
        # do something and return
    except Exception as error:
        # return error

如果我应该使用try-except,我想知道如何从中返回。我有函数式编程的背景,所以我这样想:

def move(file_path):
    try:
        # do something
        return (True, something...)
    except Exception as error:
        return (False, error)

其他例子:

def execute_query(database_cursor, query, fetch):
    if type(database_cursor) != "":
        return (1, "database_cursor isn't a valid database cursor")
    cursor.execute(query)
    if fetch == "*":
      return self.cursor.fetchall()
    yield self.cursor.fetchone()

在这种情况下,我担心用户发送的输入不是数据库。

此功能是否有任何约定?

谢谢!

更新

我是怎么做的:

来自sys import exit

def testing_something(a, b, c):
  try:
    return 0, a + b + c
  except Exception, error:
    return 1, error

error, result = testing_something(1, 2, 3)
if error:
  print error # raise error or treat.
  sys.exit(error)

我认为这样做非常聪明,现在我可以决定提高或者对待它。

2 个答案:

答案 0 :(得分:1)

在过去,我使用了类似以下的内容来确保某个用户输入是有效的"从某种意义上说它包含在列表或其他内容中。这对于验证手动文件输入以将数据加载到内存中非常有用。

def validate_choice(selection, choices):
    while selection not in choices:
        selection = input("'%s' is not a valid entry. Try again: " % selection)
    print("'%s' works! Returning..." % selection)
    return selection

result1 = validate_choice('foo', ['foo', 'bar', 'baz'])
result2 = validate_choice('boogers', ['foo', 'bar', 'baz'])

如果你试图将某种类型的东西强制转换为另一种类型,那么这是另一个强制用户输入A)整数或B)可以强制转换为整数的数字的例子:

def str_to_int_validation(num):
    parsed = False
    while not parsed:
        try:
            num = input("Enter an integer: ")
            num = int(num)
            parsed = True
        except ValueError:
            print("'%s' is not an integer. Try again.")
    return num

希望有所帮助!

答案 1 :(得分:0)

如果你愿意,你可以考虑使用Pythonic,但它实际上并不是一个简单的代码:

import os
import shutil

class MoveError(Exception): pass

def move (patha, pathb):
    # Some checks
    if not os.path.exists(patha):
        return MoveError("'%s' does not exist!" % patha)
    if os.path.exists(pathb):
        return MoveError("'%s' already exists! I will not overwrite it!" % pathb)
    print "Moving '%s' to '%s'..." % (patha, pathb)
    try: shutil.move(patha, pathb)
    except Exception, e:
        return MoveError("Whoops, something nasty happened! Error is:\n%s" % str(e))
    return "%i bytes moved" % os.path.getsize(pathb)

def help ():
    print "This is some help!"

def quit ():
    global running
    print "Quitting!"
    running = 0

commands = {"mv": move, "move": move, "help": help, "?": help, "q": quit, "quit": quit}
running = 1
while running:
    inp = raw_input("--> ").split()
    if not inp: continue
    try: cmd = commands[inp[0]]
    except:
        print "Invalid command '%s'" % inp[0]
        continue
    result = cmd(*inp[1:])
    if isinstance(result, Exception):
        print "Error occurred!"
    else: print "Done!"
    if result is not None:
        print result

从命令字典获取命令也可能是:

cmd = commands.get(inp[0], None)
if not cmd: print "Command doesn't exist!"

或效率低下的方式:

if inp[0]not in commands:
    print "No such command"
else: cmd = commands[inp[0]]

现在,我们可以开始争论三者中哪一个更像Pythonic。而这只是代码的这一部分。

但是,返回异常虽然可能很有吸引力,却很难做到。通常只有当你必须将某些东西推入某个库的对象以强制它捕获异常时。 (取决于lib的设计 - 很少需要)。您的原始设计,启动良好,标志指示错误,但第二件事应该是错误消息。或者继续这样,如果你觉得你出于某种原因真的需要它。但你可以随时做:

def move (pa, pb):
    raise MoveError, "I will not move anything!"

然后:

try:
    commands["move"]("somefile", "somewhereelse") # To simulate call from user input
    print "Done!"
except Exception, e:
    print "An error occurred.\n%s" % str(e)