【问题标题】:Google Flex App Engine not writing to Cloud SQL databaseGoogle Flex App Engine 未写入 Cloud SQL 数据库
【发布时间】:2018-05-31 13:25:38
【问题描述】:

编辑:已解决,见底部

我正在开展一个项目,该项目从 Meraki 扫描 API 接收数据并将该 JSON 数据写入 Cloud SQL 数据库。该代码最初可以很好地写入本地 MySQL 数据库,但我尝试了大约 800 种不同的配置和调整,但似乎没有任何效果。我在 Flex App Engine 和 Cloud SQL 之间建立了连接,数据库和表都在那里,但没有运行写入/插入语句。这是一个使用 SQLAlchemy 的 Flask 应用程序(NOT Flask_SQLAlchemy)

Meraki 扫描 API 文档供参考: https://documentation.meraki.com/MR/Monitoring_and_Reporting/Scanning_API

from api import app
from sqlalchemy import create_engine
from datetime import datetime, timedelta


engine = create_engine(app.config.get('database_uri'))
class Events(object)
@staticmethod
def add(event):
    connection = engine.connect()
    for observation in event["observations"]:
        try:
            connection.execute("""INSERT INTO events (
                apMac,
                apTags,
                apFloors,
                clientMac,
                ipv4,
                ipv6,
                seenTime,
                seenEpoch,
                ssid,
                rssi,
                manufacturer,
                os,
                lat,
                lng,
                unc,
                x,
                y
            ) VALUES (
                %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s
            )""", (
                event.get("apMac", None),
                ",".join(event.get("apTags", [])),
                ",".join(event.get("apFloors", [])),
                observation.get("clientMac", None),
                observation.get("ipv4").strip("/") if observation.get("ipv4") is not None else None,
                observation.get("ipv6", None),
                observation.get("seenTime", None),
                observation.get("seenEpoch", None),
                observation.get("ssid", None),
                observation.get("rssi", None),
                observation.get("manufacturer", None),
                observation.get("os", None),
                observation.get("location", {}).get("lat", None),
                observation.get("location", {}).get("lng", None),
                observation.get("location", {}).get("unc", None),
                observation.get("location", {}).get("x", None) if observation.get("location", {}).get("x", None) != [] else None,
                observation.get("location", {}).get("y", None) if observation.get("location", {}).get("y", None) != [] else None,
            ))
        except:
            pass

    connection.close()
    return "Added"

那是带有添加到它的函数的 Event 类。 这是另一个处理提供验证器的脚本,因此 Meraki 将开始将 JSON 数据发布到页面:

from flask import request
from api import app
from api.models import Events


@app.route('/', methods=['GET'])
def events_get():
    return str(app.config.get("validator"))


@app.route('/', methods=['POST'])
def events_post():
    data = request.json
    if data["secret"] != app.config.get("secret"):
        return
    Events.add(data["data"])
    return "."

数据库 URI 设置为(我也尝试过 mysql 以及 mysql+pymysql):

mysql+mysqldb://<user>:<pw>@/<database>?unix_socket=/cloudsql/<instance connection name>

我收到了 POST,但没有关于 Cloud SQL 的数据。任何帮助是极大的赞赏。谢谢。

解决方案:我不得不在 Cloud SQL 上恢复到 MySQL 5.6。结合 MySQL 的 ALLOW_INVALID_DATES 标志修复了这个问题,并将时间保持为 DateTime。

【问题讨论】:

    标签: python google-app-engine flask sqlalchemy google-cloud-sql


    【解决方案1】:

    尝试按照here 的建议启用 SQLAlchemy 日志记录:

    import logging
    
    logging.basicConfig()
    logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO)
    

    现在,我看到的第二件事是您捕获所有异常并且什么都不做。 一般来说,这被认为是一种不好的做法。 除此之外,它可能会给你一个线索,为什么你没有插入任何数据。 删除 try...except 或添加异常日志以查看发生了什么 - 可能对您有所帮助。

    最后,你可以尝试使用事务的方法,不确定。 来自SQLAlchemy connection docs的示例:

    trans = connection.begin()
    try:
        r1 = connection.execute(table1.select())
        connection.execute(table1.insert(), col1=7, col2='this is some data')
        trans.commit()
    except:
        trans.rollback()
        raise
    

    更新: 另外,不确定你的语法 execute("INSERT .... VALUES (%s, %s, ...), (value1, value2)) 是否有效,但如果你说它适用于本地服务器,那么你可能可以忽略这个。

    我在官方文档中看到的是
    engine.execute("insert into users values (?, ?)", 1, "john"), 即问号 ? 而不是 %s 和展开的参数,而不是列表。

    更新2: 还要确保实际调用了Events.add,将prints 放在任何地方以查看值。 在您的情况下,可能是 secret 值不匹配。

    【讨论】:

    • 发现错误。这是(_mysql_exceptions.OperationalError) (1292, "Incorrect datetime value: '2018-05-31T15:13:42Z' for column 'seenTime' at row 1")
    • @jhomr 我想你知道现在该做什么了吧?
    • 对于稍后阅读本文的任何人:我必须在 Cloud SQL 上恢复到 MySQL 5.6。结合 MySQL 的 ALLOW_INVALID_DATES 标志修复了这个问题,并将时间保持为 DateTime。
    • @jhomr 我建议将此注释添加到底部的原始问题中以提高可见性)
    猜你喜欢
    • 1970-01-01
    • 2015-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-06
    • 1970-01-01
    • 2020-11-22
    • 2018-06-25
    相关资源
    最近更新 更多