我正在为 Alexa 开发一个烧瓶应用程序。默认情况下,我们有一个 lambda_function.py,它充当名为 flask-app.py 的烧瓶应用程序。它看起来像这样:
import logging
import ask_sdk_core.utils as ask_utils
from flask import Flask
from skill.intent_requests.instrument_commands_intent.instrument_commands import instrument_commands_handler, \
get_device_command_context
from ask_sdk_core.skill_builder import SkillBuilder
from ask_sdk_core.dispatch_components import AbstractRequestHandler
from ask_sdk_core.dispatch_components import AbstractExceptionHandler
from ask_sdk_core.handler_input import HandlerInput
from ask_sdk_model import Response
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
class LaunchRequestHandler(AbstractRequestHandler):
"""Handler for Skill Launch."""
def can_handle(self, handler_input):
# type: (HandlerInput) -> bool
return ask_utils.is_request_type("LaunchRequest")(handler_input)
def handle(self, handler_input):
# type: (HandlerInput) -> Response
speak_output = "Welcome, you can say Hello or Help. Which would you like to try?"
return (
handler_input.response_builder
.speak(speak_output)
.ask(speak_output)
.response
)
class HelloWorldIntentHandler(AbstractRequestHandler):
"""Handler for Hello World Intent."""
def can_handle(self, handler_input):
# type: (HandlerInput) -> bool
return ask_utils.is_intent_name("HelloWorldIntent")(handler_input)
def handle(self, handler_input):
# type: (HandlerInput) -> Response
speak_output = "Hello World!"
return (
handler_input.response_builder
.speak(speak_output)
# .ask("add a reprompt if you want to keep the session open for the user to respond")
.response
)
class HelpIntentHandler(AbstractRequestHandler):
"""Handler for Help Intent."""
def can_handle(self, handler_input):
# type: (HandlerInput) -> bool
return ask_utils.is_intent_name("AMAZON.HelpIntent")(handler_input)
def handle(self, handler_input):
# type: (HandlerInput) -> Response
speak_output = "You can say hello to me! How can I help?"
return (
handler_input.response_builder
.speak(speak_output)
.ask(speak_output)
.response
)
class CancelOrStopIntentHandler(AbstractRequestHandler):
"""Single handler for Cancel and Stop Intent."""
def can_handle(self, handler_input):
# type: (HandlerInput) -> bool
return (ask_utils.is_intent_name("AMAZON.CancelIntent")(handler_input) or
ask_utils.is_intent_name("AMAZON.StopIntent")(handler_input))
def handle(self, handler_input):
# type: (HandlerInput) -> Response
speak_output = "Goodbye!"
return (
handler_input.response_builder
.speak(speak_output)
.response
)
class SessionEndedRequestHandler(AbstractRequestHandler):
"""Handler for Session End."""
def can_handle(self, handler_input):
# type: (HandlerInput) -> bool
return ask_utils.is_request_type("SessionEndedRequest")(handler_input)
def handle(self, handler_input):
# type: (HandlerInput) -> Response
# Any cleanup logic goes here.
return handler_input.response_builder.response
class IntentReflectorHandler(AbstractRequestHandler):
"""The intent reflector is used for interaction model testing and debugging.
It will simply repeat the intent the user said. You can create custom handlers
for your intents by defining them above, then also adding them to the request
handler chain below.
"""
def can_handle(self, handler_input):
# type: (HandlerInput) -> bool
return ask_utils.is_request_type("IntentRequest")(handler_input)
def handle(self, handler_input):
# type: (HandlerInput) -> Response
intent_name = ask_utils.get_intent_name(handler_input)
speak_output = "You just triggered " + intent_name + "."
return (
handler_input.response_builder
.speak(speak_output)
# .ask("add a reprompt if you want to keep the session open for the user to respond")
.response
)
class CatchAllExceptionHandler(AbstractExceptionHandler):
"""Generic error handling to capture any syntax or routing errors. If you receive an error
stating the request handler chain is not found, you have not implemented a handler for
the intent being invoked or included it in the skill builder below.
"""
def can_handle(self, handler_input, exception):
# type: (HandlerInput, Exception) -> bool
return True
def handle(self, handler_input, exception):
# type: (HandlerInput, Exception) -> Response
logger.error(exception, exc_info=True)
speak_output = "Sorry, I had trouble doing what you asked. Please try again."
return (
handler_input.response_builder
.speak(speak_output)
.ask(speak_output)
.response
)
app = Flask(__name__)
with app.app_context():
if os.environ['FLASK_ENV'] == 'testing':
app.config.from_object(config.TestingConfig)
elif os.environ['FLASK_ENV'] == 'staging':
app.config.from_object(config.TestingConfig)
elif os.environ['FLASK_ENV'] == 'production':
app.config.from_object(config.TestingConfig)
else:
app.config.from_object(config.Config)
sb = SkillBuilder()
sb.add_request_handler(LaunchRequestHandler())
sb.add_request_handler(HelloWorldIntentHandler())
sb.add_request_handler(HelpIntentHandler())
sb.add_request_handler(CancelOrStopIntentHandler())
sb.add_request_handler(SessionEndedRequestHandler())
sb.add_request_handler(IntentReflectorHandler()) # make sure IntentReflectorHandler is last so it doesn't override your custom intent handlers
sb.add_exception_handler(CatchAllExceptionHandler())
lambda_handler = sb.lambda_handler()
skill_adapter.register(app=app, route="/")
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8080)
我还有一个 config.py,用于根据环境变量(测试、阶段、产品)加载不同的变量,如下所示:
class Config(object):
PLATFORM_API_ROOT_URL = 'localhost'
DEVICE_CONTEXT_API = 'cl-voice-connect-service-test'
class TestingConfig(Config):
PLATFORM_API_ROOT_URL = 'localhost'
DEVICE_CONTEXT_API = 'cl-voice-connect-service-test'
class ProductionConfig(Config):
PLATFORM_API_ROOT_URL = 'localhost'
DEVICE_CONTEXT_API = 'cl-voice-connect-service-prod'
class StagingConfig(Config):
PLATFORM_API_ROOT_URL = 'localhost'
DEVICE_CONTEXT_API = 'cl-voice-connect-service-stage'
我想根据环境为 app.config 分配特定的值。所以还有另一个名为 instrument_commands.py 的文件,我想在其中访问 app.config[PLATFORM_API_ROOT_URL]。在instrument_commands.py 中,我从flask-app.py 导入app 对象,就像“从flask import current_app as app”一样。由于这些行是在创建应用程序对象之前执行的,因此出现错误:
RuntimeError:在应用程序上下文之外工作。
这通常意味着您尝试使用需要以某种方式与当前应用程序对象交互的功能。要解决此问题,请使用 app.app_context() 设置应用程序上下文。
为什么会发生这种情况甚至在初始化 app 对象之前,它的调用
from skill.intent_requests.instrument_commands_intent.instrument_commands
import instrument_commands_handler, \
get_device_command_context
在那里它找不到应用程序上下文。如何在 app 对象调用特定的 python 类之前初始化它。对不起,如果我做错了什么,因为这对我来说是新的。
谢谢