国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Python > 正文

Python的Tornado框架實現(xiàn)異步非阻塞訪問數(shù)據(jù)庫的示例

2019-11-25 16:40:40
字體:
供稿:網(wǎng)友

tornado即是一個http非阻塞服務(wù)器, 就要用起來, 我們將用到tornado框架 ,mongodb數(shù)據(jù)庫 以及motor(mongodb的異步驅(qū)動).來簡單實現(xiàn)tornado的非阻塞功能.

其他環(huán)境支持的下載與安裝

1.安裝mongodb

$ sudo apt-get install update$ sudo apt-get install mongodb

2.安裝motor

$ pip install motor

非阻塞

# conf.pyimport osimport motorfrom handlers import index, authBASE_DIR = os.path.join(__file__)handlers = [  (r'^/$', index.IndexHandler),  (r'^/auth/register$', auth.RegisterHandler),  (r'^/auth/login$', auth.LoginHandler),]settings = dict(  debug = True,  template_path = os.path.join(BASE_DIR, 'templates'),  static_path = os.path.join(BASE_DIR, 'static'),)client = motor.MotorClient("127.0.0.1")db = client.meet

首先在配置文件中連接數(shù)據(jù)庫, client.db_name中 db_name就是數(shù)據(jù)庫的名稱

 # handlers/__init__.pyclass BaseHandler(tornado.web.RequestHandler, TemplateRendering):  def initialite(self):    ...  @property  def db(self):    return self.application.db

添加db()并使用property裝飾,像屬性一樣訪問數(shù)據(jù)庫.

# auth.pyimport os import time import tornado.webfrom tornado import genfrom . import BaseHandlerclass RegisterHandler(BaseHandler):  def get(self):    self.render_html('register.html')  @tornado.web.asynchronous  @gen.coroutine  def post(self):    username = self.get_argument('username', None)    email = self.get_argument('email', None)    password = self.get_argument('password', None)    data = {      'username': username,      'email': email,      'password': password,      'timestamp': time.time() * 1000,    }    if username and email:      yield self.db.user.insert(data)    self.redirect('/')class LoginHandler(BaseHandler):    @tornado.web.asynchronous  @gen.coroutine  def get(self):    username = self.get_argument('useranme')    user = yield self.db.user.find_one({'username': username})    self.render_html('login.html', user=user)

@gen.coroutine裝飾使函數(shù)非阻塞, 返回一個生成器, 而不用在使用回調(diào)函數(shù). motor也通過yield 實現(xiàn)異步(不然還得返回一個回調(diào)函數(shù)). 其實這個例子反映不了阻塞問題關(guān)鍵是時間太短.
我們修改一下代碼

# 之前yield self.db.user.insert(data)# 之后yield tornado.gen.Task(tornado.ioloop.IOLoop.instance().add_timeout, time.time() + 10)

這里通過tornado.ioloop.IOLoop.instance().add_timeout阻塞應(yīng)用, 這是time.sleep的非阻塞實現(xiàn), 如果這里使用time.sleep因為是tornado是單線程會阻塞整個應(yīng)用所以別的handler也無法訪問.
可以看到我在注冊頁面注冊后,在阻塞期間點擊/auth/login直接就訪問了login頁完成非阻塞.

異步下的redirect問題
在使用tornado的時候常常遇到一些問題, 特將遇到的問題和解決的方法寫出來(這里的感謝一下幫我解答疑惑的pythonista們)

1.問題

我想要實現(xiàn)一個注冊用戶功能, web框架使用tornado數(shù)據(jù)庫使用mongodb但在注冊時出現(xiàn)Exception redirect的錯誤. 現(xiàn)貼下代碼:

class Register(BaseHandler):  def get(self):    self.render_html('register.html')  @tornado.web.aynchronous  @gen.coroutine  def post(self):    username = self.get_argument('username')    email = self.get_argument('email')    password = self.get_argument('password')    captcha = self.get_argument('captcha')    _verify_username = yield self.db.user.find_one({'username': username})    if _verify_username:      self.flash(u'用戶名已存在', 'error')      self.redirect('/auth/register')    _verify_email = yield self.db.user.find_one({'email': email})    if _verify_email:      self.flash(u'郵箱已注冊', 'error')      self.redirect('/auth/register')    if captcha and captcha == self.get_secure_cookie('captcha').replace(' ',''):      self.flash(u'驗證碼輸入正確', 'info')    else:      self.flash(u'驗證碼輸入錯誤', 'error')      self.redirect('/auth/register')    password = haslib.md5(password + self.settings['site']).hexdigest()    profile = {'headimg': '', 'site': '', 'job': '', 'signature':'',          'github': '', 'description': ''}    user_profile = yield self.db.profile.insert(profile)    user = {'username': username, 'email': email, 'password': password,        'timestamp': time.time(), 'profile_id': str(user_profile)}    yield self.db.user.insert(user)    self.set_secure_cookie('user', username)    self.redirect('/')

本想如果用戶驗證碼輸入出錯就跳轉(zhuǎn)到注冊頁面, 但問題是驗證碼出錯也會繼續(xù)執(zhí)行一下代碼. 雖然在self.redirect后加上self.finish會終止代碼,但是因為self.redirect 函數(shù)內(nèi)已有self.finish所以出現(xiàn)了兩次報出異常終止的代碼.
因為以上原因代碼不會被終結(jié), 驗證碼出錯用戶還是會注冊.

2.解決方案

return self.redirect('/auth/register')


self.redirect('/auth/register')return

(1)segmentdefault中熱心用戶rsj217給出的答案
self.finish 會關(guān)掉請求, 因為@tornado.web.aynchronous告訴tornado會一直等待請求(長鏈接). self.redirect等于設(shè)置了response的headers的location屬性.

(2)segmentdefault中熱心用戶依云給出的答案
self.finish當(dāng)然不會跳出函數(shù), 不然請求結(jié)束之后還想做些事情怎么辦呢.

3.總結(jié)

因為錯把self.finish當(dāng)做跳出函數(shù)出現(xiàn)了以上的問題

  • self.redirect會在request.headers 里設(shè)置location用于跳轉(zhuǎn)
  • self.finish會關(guān)掉請求, 但不會跳出函數(shù)
發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 布尔津县| 腾冲县| 买车| 周口市| 宜宾县| 大荔县| 且末县| 周口市| 宕昌县| 龙口市| 海伦市| 泸水县| 三江| 墨竹工卡县| 蓬安县| 马山县| 柯坪县| 新巴尔虎右旗| 镇宁| 吉木萨尔县| 万荣县| 丹阳市| 滨州市| 湖北省| 沙湾县| 略阳县| 衢州市| 康保县| 迭部县| 芦山县| 台东市| 灵山县| 丰县| 三亚市| 郧西县| 阳原县| 宁阳县| 如皋市| 鹿邑县| 泸西县| 德庆县|