to jest nowy rozdział
413
Co robić,
gdy sprawy idą źle
11. Obsługa wyjątków
Sprawy idą źle, dzieje się tak zawsze niezależnie od tego, jak dobry jest Twój kod.
Jak do tej pory wszystkie przykłady przedstawione w tej książce bez problemu udawało Ci się uruchomić
i raczej jesteś pewien, że zaprezentowany dotąd kod działa. Czy oznacza to jednak, że kod ten jest solidny?
Raczej nie. Pisanie kodu w oparciu o założenie, że nic złego nie może się zdarzyć, jest (w najlepszym
przypadku) oznaką naiwności. W najgorszym przypadku jest to wręcz praktyka niebezpieczna, poniew
nieprzewidziane rzeczy się zdarzają (i będą się zdarzać). Lepiej, abyś tworząc kod, był ostrożny niż beztroski.
Ostrożność jest konieczna, aby mieć pewność, że Twój kod robi to, czego od niego oczekujesz, jak również że
reaguje prawidłowo, gdy rzeczy idą w złą stronę. W niniejszym rozdziale dowiesz się nie tylko tego, co może
pójść nie tak, lecz również co robić, gdy to się stanie (a częstokroć jeszcze zanim to nastąpi).
Sprawdziłem
wytrzymałość tej liny
na zerwanie... Co złego
może się stać?
414
Rozdział 11.
Szukanie problemów
Długie ćwiczenie
Zaczniemy ten rozdział od skoku na głęboką wodę. Poniżej została zaprezentowana ostatnia wersja kodu
aplikacji WWW
vsearch4web.py
. Jak możesz się przekonać, zaktualizowaliśmy ten kod w taki sposób, aby
korzystał z dekoratora check_logged_in, który został przedstawiony w poprzednim rozdziale, w celu
kontrolowania, kiedy informacje prezentowane na stronie związanej z URL-em /viewlog(lub nie są)
widoczne dla użytkowników.
Poświęć tyle czasu, ile tylko Ci trzeba, aby przeczytać ten kod, a następnie użyj ołówka, aby zakreślić
i skomentować te części kodu, które Twoim zdaniem mogą powodować problemy podczas działania
w środowisku produkcyjnym. Wskaż
wszystko
, co — jak sądzisz — może być przyczyną kłopotów,
nie jedynie potencjalne problemy czy błędy czasu wykonania.
from flask import Flask, render_template, request, escape, session
from vsearch import search4letters
from DBcm import UseDatabase
from checker import check_logged_in
app = Flask(__name__)
app.config[‘dbconfig’] = {‘host’: ‘127.0.0.1’,
‘user’: ‘vsearch’,
‘password’: ‘vsearchpasswd’,
‘database’: ‘vsearchlogDB’, }
@app.route(‘/login’)
def do_login() -> str:
session[‘logged_in’] = True
return ‘Teraz jesteś zalogowany.’
@app.route(‘/logout’)
def do_logout() -> str:
session.pop(‘logged_in’)
return ‘Teraz jesteś wylogowany.’
def log_request(req: ‘flask_request’, res: str) -> None:
with UseDatabase(app.config[‘dbconfig’]) as cursor:
_SQL = ”””insert into log
(phrase, letters, ip, browser_string, results)
values
(%s, %s, %s, %s, %s)”””
cursor.execute(_SQL, (req.form[‘phrase’],
req.form[‘letters’],
req.remote_addr,
req.user_agent.browser,
res, ))
jesteś tutaj
415
Obsługa wytków
@app.route(‘/search4’, methods=[‘POST’])
def do_search() -> ‘html’:
phrase = request.form[‘phrase’]
letters = request.form[‘letters’]
title = ‘Oto Twoje wyniki:’
results = str(search4letters(phrase, letters))
log_request(request, results)
return render_template(‘results.html’,
the_title=title,
the_phrase=phrase,
the_letters=letters,
the_results=results,)
@app.route(‘/’)
@app.route(‘/entry’)
def entry_page() -> ‘html’:
return render_template(‘entry.html’,
the_title=’Witamy na stronie internetowej
search4letters!’)
@app.route(‘/viewlog’)
@check_logged_in
def view_the_log() -> ‘html’:
with UseDatabase(app.config[‘dbconfig’]) as cursor:
_SQL = ”””select phrase, letters, ip, browser_string, results
from log”””
cursor.execute(_SQL)
contents = cursor.fetchall()
titles = (‘Fraza’ , ‘Litery’ , ‘Adres klienta’, ‘Agent użytkownika’, ‘Wyniki’)
return render_template(‘viewlog.html’,
the_title=’View Log’,
the_row_titles=titles,
the_data=contents,)
app.secret_key = ‘NigdyNieZgadnieszMojegoTajnegoKlucza’
if __name__ == ‘__main__’:
app.run(debug=True)
416
Rozdział 11.
Rozpoznawanie problemów
Długie ćwiczenie
Miałeś poświęcić tyle czasu, ile tylko było trzeba, aby przeczytać przedstawiony poniżej kod (będący zaktualizowaną
wersją kodu aplikacji WWW
vsearch4web.py
). Następnie, używając ołówka, miałeś zakreślić i skomentować te jego
części, które Twoim zdaniem mogą powodować problemy podczas działania w środowisku produkcyjnym. Powinieneś
był wskazać
wszystko
, co — jak sądzisz — może być przyczyną kłopotów, nie jedynie potencjalne problemy czy błędy
czasu wykonania. (Ponumerowaliśmy nasze komentarze, aby łatwiej było się do nich odwoływać).
from flask import Flask, render_template, request, escape, session
from vsearch import search4letters
from DBcm import UseDatabase
from checker import check_logged_in
app = Flask(__name__)
app.config[‘dbconfig’] = {‘host’: ‘127.0.0.1’,
‘user’: ‘vsearch’,
‘password’: ‘vsearchpasswd’,
‘database’: ‘vsearchlogDB’, }
@app.route(‘/login’)
def do_login() -> str:
session[‘logged_in’] = True
return ‘Teraz jesteś zalogowany.’
@app.route(‘/logout’)
def do_logout() -> str:
session.pop(‘logged_in’)
return ‘Teraz jesteś wylogowany.’
def log_request(req: ‘flask_request’, res: str) -> None:
with UseDatabase(app.config[‘dbconfig’]) as cursor:
_SQL = ”””insert into log
(phrase, letters, ip, browser_string, results)
values
(%s, %s, %s, %s, %s)”””
cursor.execute(_SQL, (req.form[‘phrase’],
req.form[‘letters’],
req.remote_addr,
req.user_agent.browser,
res, ))
3. Co się stanie, gdy
wykonanie tych instrukcji SQL
będzie trwało zbyt długo?
2. Czy te instrukcje SQL
chronione przed paskudnymi,
wykorzystującymi sieć atakami,
takimi jak wstrzyknięcie kodu
SQL (ang. SQL injection) lub
wstrzyknięcie skryptu (ang.
Cross-site scripting)?
1. Co się stanie, gdy
połączenie z bazą danych
się nie powiedzie?
Rozwiązanie
jesteś tutaj
417
Obsługa wytków
4. Co się stanie,
gdy ta operacja
się nie uda?
@app.route(‘/search4’, methods=[‘POST’])
def do_search() -> ‘html’:
phrase = request.form[‘phrase’]
letters = request.form[‘letters’]
title = ‘Oto Twoje wyniki:’
results = str(search4letters(phrase, letters))
log_request(request, results)
return render_template(‘results.html’,
the_title=title,
the_phrase=phrase,
the_letters=letters,
the_results=results,)
@app.route(‘/’)
@app.route(‘/entry’)
def entry_page() -> ‘html’:
return render_template(‘entry.html’,
the_title=’Witamy na stronie internetowej search4letters!’)
@app.route(‘/viewlog’)
@check_logged_in
def view_the_log() -> ‘html’:
with UseDatabase(app.config[‘dbconfig’]) as cursor:
_SQL = ”””select phrase, letters, ip, browser_string, results
from log”””
cursor.execute(_SQL)
contents = cursor.fetchall()
titles = (‘Fraza’ , ‘Litery’ , ‘Adres klienta’, ‘Agent użytkownika’, ‘Wyniki’)
return render_template(‘viewlog.html’,
the_title=’View Log’,
the_row_titles=titles,
the_data=contents,)
app.secret_key = ‘NigdyNieZgadnieszMojegoTajnegoKlucza’
if __name__ == ‘__main__’:
app.run(debug=True)

Get Python Rusz głową! Wydanie II now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.