首页 > 解决方案 > 异常触发:“NoneType”对象没有属性“app”

问题描述

在此处输入图像描述

使用 Python3 和 Flask 时出错。

在下面显示的代码中,您会注意到我已将端口定义为 8080。将其定义为端口 80 在我拥有的另一个应用程序中运行良好,该应用程序可以浇灌我的室内植物并在动态网页上显示结果,但在这里它因权限被拒绝错误而崩溃。为什么,鉴于两者都是在 Raspbian 上使用相同版本以完全相同的方式创建的?

但这还不是问题。真正的问题是为什么它甚至不能在同一个应用程序中保持一致。

#!/usr/bin/python3
from flask import Flask, render_template, redirect, url_for
from imapclient import IMAPClient 
import email
import time 
import sys
import os
from concurrent.futures import ThreadPoolExecutor
executor = ThreadPoolExecutor(1) # number of executor
import logging 

logging.basicConfig(filename='/home/pi/mailbox_event.log',level=logging.WARNING)
HOSTNAME = 'imap.plus.net' 
USERNAME = 'megapower+rob' 
PASSWORD = 'aqp-hRM-2Nb-qh9'

MAILBOX = 'INBOX' 
NEWMAIL_OFFSET = 0 
MAIL_CHECK_FREQ = 10 #number of seconds for mail check

m1 = ""
m2 = ""
m3 = ""
m4 = ""

app = Flask(__name__)

def TimeNowIs():
    TimeNow = time.strftime('%d/%m/%Y at %H:%M:%S')
    return TimeNow

print("Hi" )
print("Mailbox here")
print("Just starting up")
logging.info("Mailbox App starting up")

def template(title = "Mail Display!", text = TimeNowIs(), m1 = " ", m2 = " ", m3 = " ", m4 = " "):
    text, m1, m2, m3, m4 = ""
    templateData = {
        'title' : title,
        'text' : text,
        'm1' : m1,
        'm2' : m2,
        'm3' : m3,
        'm4' : m4
        }
    return templateData

@app.route("/")

def main():
    text = TimeNowIs()
    m1 = "Hi"
    m2 = "Mailbox here"
    m3 = "Just starting up"
    m4 = "Going to check your mail"

    list_object = [text, m1, m2, m3, m4]
    return render_template('main.html', text_to_send = list_object)

def getmail():
    try:
        print("Logging in")
        server = IMAPClient(HOSTNAME, use_uid=True, ssl=False)
        server.login(USERNAME, PASSWORD)
        server.select_folder('INBOX', readonly=True)
    except:
        connected = False
        server = ""
        logging.warning('Logon failed')
        print("Logon failed")
    else:
        connected = True
        print("Logon succeeded")

        messages = server.search('UNSEEN')
        print("we have %d unread emails." % len(messages))

        for uid, message_data in server.fetch(messages, 'RFC822').items():
            email_message = email.message_from_bytes(message_data[b'RFC822'])
            m1 = (uid, email_message.get('From'), email_message.get('Subject')) 
            print(m1)

        text = TimeNowIs()
        m1 = "Well now"
        m2 = "I've checked your mail"
        m3 = "you should see something here"
        m4 = "that isn't the start up message"

        list_object = [text, m1, m2, m3, m4]

        print("Logging out")
        server.logout()
    return render_template('main.html', text_to_send = list_object)


def printmail():
    try:
        while True:
            os.system("clear")
            timeString = time.strftime('%d/%m/%Y at %H:%M:%S')
            print("Checking mail")
            print(timeString)
            getmail()

            print("Waiting")
            time.sleep(MAIL_CHECK_FREQ)

    except KeyboardInterrupt:
        print("Shutting down")
        logging.info('System closed by Ctrl-C')
        print("Goodbye")
        #os.system("sudo reboot")

    except Exception as e:
        logging.warning('Exception triggered: ' + str(e))
        print("Exception triggered: " + str(e))
#        os.system("sudo reboot")
    pass
    return

if __name__ == "__main__":
    executor.submit(printmail)
    app.run(host='0.0.0.0', port=8080, debug=True)

我在这里努力的是 printmail() 作为永恒循环运行的场景,除非被杀死或发生致命异常,然后将记录该异常,然后 Pi 重新启动。您将从所附图像中看到 main() 运行并且 list_object 被写入网页。

但是,当调用 getmail() 时,m1 会被写入终端,所以我知道我们可以到那里,但是 render_template 失败,'NoneType' 对象没有属性'app'。

我想知道自从返回 render_template 行之后会怎样,并且创建 list_object 的代码与 main() 中的代码相同

标签: pythonpython-3.xflask

解决方案


Flask render_template 函数期望能够访问flask 应用程序上下文。你可以在这里看到 render_template 的实现: https ://github.com/pallets/flask/blob/1351d0a56580df36872b466eb245e7634c20dab5/src/flask/templating.py#L125-L141

from .globals import _app_ctx_stack

ctx = _app_ctx_stack.top ctx.app.update_template_context(context) return _render( ctx.app.jinja_env.get_or_select_template(template_name_or_list), context, ctx.app, )

您需要找到一种方法让您的执行程序线程可以访问烧瓶本地堆栈上下文。


推荐阅读