什么是Python异常? (What’s a Python Exception?)
This tutorial will introduce you to exceptions and how to handle exceptions in Flask. By the end of this tutorial, you’ll be able to create custom exceptions for your code.
本教程将向您介绍异常以及如何在Flask中处理异常。 在本教程结束时,您将能够为代码创建自定义异常。
while True:
number = int(input('Please enter a number between 1 and 10: '))
print(number**2)
Run the program, and enter a string instead of a number as the input. If you run the program, it’ll work as long as the input is an integer. If you input a string instead of a number, you’ll get a ValueError
, as shown below.
运行该程序,然后输入字符串而不是数字作为输入。 如果您运行该程序,只要输入是整数,它就可以工作。 如果输入字符串而不是数字,则会出现ValueError
,如下所示。
Please enter a number between 1 and 10: fur
Traceback (most recent call last):
File “main.py”, line 9, in <module>
number = int(input(‘Please enter a number between 1 and 10: ‘))
ValueError: invalid literal for int() with base 10: ‘b’
The program above calculates the square of the number entered by the user. But suppose the user instead enters a string or a special character, if the program doesn’t check if the input is a valid integer, the program will throw an exception.
上面的程序计算用户输入的数字的平方。 但是,假设用户输入的是字符串或特殊字符,如果程序未检查输入是否为有效整数,则程序将引发异常。
Therefore, it’s important to catch errors where they occur instead of waiting for the whole program to crash. We’ll include try
/except
clauses to catch any errors that might occur in the program. The program will look like this:
因此,重要的是在发生错误的地方捕获错误,而不是等待整个程序崩溃。 我们将包括try
/ except
子句,以捕获程序中可能发生的任何错误。 该程序将如下所示:
while True:
try:
number = int(input('Please enter a number between 1 and 10: '))
print(number**2)
except ValueError:
print('Please enter a valid integer')
In Python, we use try
and except
blocks to catch and handle exceptions. The code after the try
statement is Python executed as a normal part of the program. After the except
statement, the code is the program’s response to any exceptions in the preceding try clause.
在Python中,我们使用try
和except
块来捕获和处理异常。 try
语句之后的代码是Python作为程序的正常部分执行的。 在except
语句之后,代码是程序对前面try子句中任何异常的响应。
为什么在Flask中处理异常很重要? (Why Is It Important to Handle Exceptions in Flask?)
Enables the smooth flow of programs: Handling exceptions at every possible aspect allows your code to run smoothly regardless of any errors
使程序顺畅地进行:处理各个方面的异常可以使代码顺利运行,而不管任何错误
Security purposes: Handling exceptions from a security point also helps secure your programs since you’re unlikely to leak or expose your code’s configurations to random people
安全目的:从安全角度处理异常也有助于保护程序,因为您不太可能将代码的配置泄漏或暴露给随机的人
Flask REST API示例 (Flask REST API example)
You’ll use the Flask API to implement your own browsable API.
您将使用Flask API来实现自己的可浏览API。
You’ll develop a REST API for a library store. The API will be able to:
您将为库存储开发REST API。 该API将能够:
- Add a new book entry 添加新书条目
- View all the books available in the library 查看图书馆中所有可用的书籍
先决条件 (Prerequisites)
The project will use the following dependencies
该项目将使用以下依赖项
- Python Python
- Flask 烧瓶
- Flask-SQLAlchemy Flask-SQLAlchemy
- Flask API 烧瓶API
- Create a new project. 创建一个新项目。
mkdir library
2. Create and activate the virtual environment.
2.创建并激活虚拟环境。
cd library
python3.6 -m venv env
source env/bin/activate
3. Install all the dependencies.
3.安装所有依赖项。
(env)$ pip install flask
(env)$ pip install flask-sqlalchemy
(env)$ pip install flask-api
(env)$ pip freeze > requirements.txt
4. Create files and folders to match the directory structure shown below:
4.创建文件和文件夹以匹配如下所示的目录结构:
数据库配置 (Database configurations)
You’ll use the SQLite database and Flask-SQLAlchemy. Flask-SQLAlchemy is a Flask extension that provides support for SQLAlchemy.
您将使用SQLite数据库和Flask-SQLAlchemy。 Flask-SQLAlchemy是Flask扩展,它提供对SQLAlchemy的支持。
Define configurations for the database.
定义数据库的配置。
Inside the app/__init__.py
file, and add the following:
在app/__init__.py
文件中,添加以下内容:
#app/__init__.py`
from flask_sqlalchemy import SQLAlchemy
from flask_api import FlaskAPI
app = FlaskAPI(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///library_db.db"
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
Models
楷模
Add the following to the models.py
file:
将以下内容添加到models.py
文件中:
from sqlalchemy import String, Integer, DateTime
import datetime
from app import db
class Book(db.Model):
id = db.Column(db.Integer, primary_key=True)
book_name = db.Column(db.String(80), unique=True)
date_created = db.Column(db.DateTime, default=datetime.datetime.utcnow)
def __init__(self, book_name):
self.book_name = book_name
def __repr__(self):
return "<Book %r>" % self.book_name
def to_json(self):
return {
'id': self.id,
'book_name': self.book_name,
'date_created': self.date_created
}
Next, define an entry point to start your app. Inside the run.py
file, add the following code:
接下来,定义一个入口点以启动您的应用程序。 在run.py
文件中,添加以下代码:
from app import app, db
from app.models import Book
if __name__ == "__main__":
db.create_all()
app.run(debug=True)
db.create.all()
will create database tables when you run the app for the first time. Setting debug = true
is important for debugging the app, but it’s not recommended in production.
db.create.all()
运行应用程序时, db.create.all()
将创建数据库表。 设置debug = true
对于调试应用程序很重要,但是不建议在生产中使用。
Run the following command in the terminal:
在终端中运行以下命令:
(env)$ python run.py
Let’s define the first route and see how to handle exceptions. In the run.py
file, add the following:
让我们定义第一个路由,看看如何处理异常。 在run.py
文件中,添加以下内容:
from flask import jsonify, request
from flask_api import status
from app import app, db
from app.models import Book
@app.route('/books', methods=['GET', 'POST'])
def index():
if request.method == 'GET':
all_books = Book.query.all()
results = [t.to_json() for t in all_books]
return results, status.HTTP_201_CREATED
elif request.method == 'POST':
if 'book_name' in request.data:
book_name = request.data['book_name']
if book_name:
new_book = Task(book_name=book_name)
db.session.add(new_book)
db.session.commit()
response = new_book.to_json()
return response, status.HTTP_201_CREATED
Now run the app again:
现在再次运行该应用程序:
python run.py
Navigate to http://localhost:5000/books/
on your browser, and you should see an empty list of books because you haven’t added any book entries yet. Add several book entries, and refresh the page.
在浏览器上导航至http://localhost:5000/books/
,由于您尚未添加任何图书条目,因此应该看到一个空白的图书列表。 添加一些书籍条目,然后刷新页面。
Handling exceptions
处理异常
The POST request expects data from the user. However, this program can go wrong if there isn’t any input data to send. The code will throw an error, as shown in this stack trace.
POST请求需要来自用户的数据。 但是,如果没有任何要发送的输入数据,该程序可能会出错。 该代码将引发错误,如此堆栈跟踪中所示。
Therefore, you’ll want to raise an exception if no data is present in the POST request. Flask comes with built-in exceptions that you can raise. You can also use a subclass of the APIException
. We’ll use the APIException
class to raise an exception if there’s no data in the POST request.
因此,如果POST请求中没有数据,则将引发异常。 Flask带有可以引发的内置异常。 您还可以使用APIException
的子类。 如果POST请求中没有数据,我们将使用APIException
类引发异常。
Create a file,
error.py
, in the app directory, and add the code below.在应用目录中创建一个文件
error.py
,并添加以下代码。
from flask_restful import APIException
class InvalidParameter(APIException):
status_code = 204
detail = 'Invalid parameters'
2. Edit the POST request to raise the InvalidParameter
exception.
2.编辑POST请求以引发InvalidParameter
异常。
from app.errors import InvalidParameter
#rest of the imports here
@app.route('/books', methods=['GET', 'POST'])
def index():
#rest of the code here
elif request.method == 'POST':
if 'book_name' in request.data:
book_name = request.data['book_name']
if book_name:
new_book = Task(book_name=book_name)
db.session.add(new_book)
db.session.commit()
response = new_book.to_json()
return response, status.HTTP_201_CREATED
raise InvalidParameter
#rest of the code here
3. Now when you perform a POST request with no data, the response will look something like this:
3.现在,当您执行不带数据的POST请求时,响应将如下所示:
HTTP 404 NOT FOUND
Content-Type: application/json
{
“message”: “Invalid parameters”
}
自定义错误 (Custom errors)
Sometimes if a route doesn’t exist, you might want to return a 404 error — e.g., the ID number of a book like this: http://127.0.0.1:5000/books/20000
may exist. If the user tries to access such an URL, a route is executed and will return a 404 error like this:
有时,如果一条路线不存在,您可能想返回404错误-例如,像这样的书的ID号: http://127.0.0.1:5000/books /20000
: http://127.0.0.1:5000/books /20000
: http://127.0.0.1:5000/books /20000
books http://127.0.0.1:5000/books /20000
可能存在。 如果用户尝试访问此类URL,则会执行路由,并会返回404错误,如下所示:
Not Found
The requested URL was not found on the server. If you entered the URL manually, please check your spelling and try again.
A 404 error is shown whenever a page isn’t found; it’s essential to have a custom error page whenever a user navigates to a page that doesn’t exist.
每当找不到页面时,都会显示404错误; 每当用户导航到不存在的页面时,必须有一个自定义错误页面。
You can create a customized 404 page to handle this kind of error. You’ll need to create a 404 template file and a 404 function in the __init__.py
file.
您可以创建自定义的404页面来处理这种错误。 您需要在__init__.py
文件中创建404模板文件和404函数。
Create a new file called
404.html
in thetemplates
folder in theapp
directory, and add the following:在
app
目录的templates
文件夹中创建一个名为404.html
的新文件,并添加以下内容:
{% block body %}
<h1>Page Not Found</h1>
<p>Woops, that page doesn’t exist! (404)</p>
<p>Take me back <a href=”{{ url_for(‘index’) }}”>HOME</a>
{% endblock %}
2. Next, add the error handler wrapper to the __init__.py
file.
2.接下来,将错误处理程序包装器添加到 __init__.py
文件。
from flask import request, render_template
#rest of the code goes here
@app.errorhandler(404)
def page_not_found(e):
return render_template('404.html'), 404
3. Don’t forget the import for rendering the template.
3.不要忘记导入来渲染模板。
from flask import request, render_template
4. Now when a user navigates to a page that doesn’t exist, they’ll see this message:
4.现在,当用户导航到不存在的页面时,他们将看到以下消息:
Page Not Found
网页未找到
Woops, that page doesn’t exist! (404)
糟糕,该页面不存在! (404)
Take me back HOME
带我回到首页
结论 (Conclusion)
Hopefully, this article has helped you understand how to deal with exceptions. You can find more information on the Flask documentation site.
希望本文能帮助您了解如何处理异常。 您可以在Flask 文档站点上找到更多信息。
翻译自: https://medium.com/better-programming/how-to-handle-exceptions-in-flask-b1d9c151875b