【问题标题】:Unable to connect to Google Cloud SQL from development server using SQLAlchemy无法使用 SQLAlchemy 从开发服务器连接到 Google Cloud SQL
【发布时间】:2013-01-08 21:53:55
【问题描述】:

我从我的开发工作站使用 SQLAlchemy 0.7.9 连接到 Google Cloud SQL 失败(希望使用 create_all() 生成架构)。我无法通过以下错误:

sqlalchemy.exc.DBAPIError: (AssertionError) No api proxy found for service "rdbms" None None

我能够使用google_sql.py instancename 成功连接到数据库实例,它最初打开了一个浏览器来授权连接(现在似乎已经缓存了授权,尽管我没有~/Library/Preferences/com.google.cloud.plist 文件正如https://developers.google.com/cloud-sql/docs/commandline 表示我应该)

这是我用来测试连接的简单应用程序:

from sqlalchemy import create_engine

engine = create_engine('mysql+gaerdbms:///myapp', connect_args={"instance":"test"})
connection = engine.connect()

完整的堆栈跟踪可在此处获得 - https://gist.github.com/4486641

【问题讨论】:

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


    【解决方案1】:

    事实证明,SQLAlchemy 中的 mysql+gaerdbms:/// 驱动程序仅设置为使用 rdbms_apiproxy DBAPI,它只能在从 Google App Engine 实例访问 Google Cloud SQL 时使用。我向 SQLAlchemy 提交了 ticket 以更新驱动程序,以便在不在 Google App Engine 上时使用基于 OAuth 的 rdbms_googleapi,就像 App Engine SDK 中提供的 Django driver 一样。 rdbms_googleapi 也是google_sql.py 使用的DBAPI(远程sql 控制台)。

    更新后的方言预计将成为 0.7.10 和 0.8.0 版本的一部分,但在它们可用之前,您可以执行以下操作:


    1 - 将ticket 中的更新方言复制到文件(例如 gaerdbms_dialect.py)

    from sqlalchemy.dialects.mysql.mysqldb import MySQLDialect_mysqldb
    from sqlalchemy.pool import NullPool
    import re
    
    """Support for Google Cloud SQL on Google App Engine
    
    Connecting
    -----------
    
    Connect string format::
    
        mysql+gaerdbms:///<dbname>?instance=<project:instance>
    
    
      # Example:
      create_engine('mysql+gaerdbms:///mydb?instance=myproject:instance1')
    """
    
    
    class MySQLDialect_gaerdbms(MySQLDialect_mysqldb):
    
        @classmethod
        def dbapi(cls):
            from google.appengine.api import apiproxy_stub_map
    
            if apiproxy_stub_map.apiproxy.GetStub('rdbms'):
                from google.storage.speckle.python.api import rdbms_apiproxy
                return rdbms_apiproxy
            else:
                from google.storage.speckle.python.api import rdbms_googleapi
                return rdbms_googleapi
    
        @classmethod
        def get_pool_class(cls, url):
            # Cloud SQL connections die at any moment
            return NullPool
    
        def create_connect_args(self, url):
            opts = url.translate_connect_args()
            opts['dsn'] = ''  # unused but required to pass to rdbms.connect()
            opts['instance'] = url.query['instance']
            return [], opts
    
        def _extract_error_code(self, exception):
            match = re.compile(r"^(\d+):").match(str(exception))
            code = match.group(1)
            if code:
                return int(code)
    
    dialect = MySQLDialect_gaerdbms
    

    2 - 注册自定义方言(您可以覆盖现有架构)

    from sqlalchemy.dialects import registry
    registry.register("mysql.gaerdbms", "application.database.gaerdbms_dialect", "MySQLDialect_gaerdbms")
    

    注意: 0.8 允许在当前进程中注册方言(如上所示)。如果您运行的是旧版本的 SQLAlchemy,我建议升级到 0.8+,否则您需要按照here 所述为方言创建单独的安装。


    3 - 更新您的 create_engine('...') url,因为项目和实例现在作为 URL 查询字符串的一部分提供

    mysql+gaerdbms:///<dbname>?instance=<project:instance>
    

    例如:

    create_engine('mysql+gaerdbms:///mydb?instance=myproject:instance1')
    

    【讨论】:

    • 你有最新的 SDK 吗?我尝试了 SQLAlchemy 0.8.0 附带的方言和您在上面发布的方言,但仍然得到这里描述的相同错误:stackoverflow.com/questions/16192979/…
    • 我找到了解决方法,并更新了您的方言:stackoverflow.com/a/16198395/125967
    • 抱歉,通知 cmets 很糟糕,刚刚看到这个。当我使用本地 mysql 实例进行开发时,我是一个不同的连接字符串/驱动程序(只是默认的 mysql:// (mysql-python) 驱动程序)并且仅在我的 Flask/ 中使用我的 Production 或 ProductionDeploy 配置时使用 mysql+gaerdbms烧瓶脚本项目。我通常也不使用 dev_appserver,而只是使用标准的 WSGI 服务器。看起来是一个值得向上游推送到 SQLAlchemy 的好变化。
    • 我开了一张票,提出改进的方言。我认为您将它与开发服务器一起使用是错误的。嗯,现在也可以这样使用。谢谢您的帮助。 :)
    【解决方案2】:

    我想我有一个如下的工作示例脚本。你能尝试类似的事情并告诉我进展如何吗?

    但是(您可能已经意识到了),如果您的目标是在 Google Cloud SQL 实例上创建架构,也许您可​​以针对本地 mysql 服务器创建架构,使用 mysqldump 转储它,然后导入架构到 Google Cloud SQL。无论如何,使用本地 mysql 服务器进行开发非常方便。

    from sqlalchemy import create_engine
    from google.storage.speckle.python.api import rdbms as dbi_driver
    from google.storage.speckle.python.api import rdbms_googleapi
    
    INSTANCE = 'YOURPROJECT:YOURINSTANCE'
    DATABASE = 'YOURDATABASE'
    
    def get_connection():       
        return rdbms_googleapi.connect('', instance=INSTANCE, database=DATABASE)
    
    def main():
        engine = create_engine(
            'mysql:///YOURPROJECT:YOURINSTANCE/YOURDATABASE',
            module=dbi_driver,
            creator=get_connection,
        )
        print engine.execute('SELECT 1').scalar()
    
    if __name__ == '__main__':
        main()
    

    【讨论】:

    • 这行得通,我可以在SELECT 1 上运行。它也像 google_sql.py 一样通过了 OAuth 流程。
    • 昨晚我看了很多现有的mysql+gaerdbms:///方言(goo.gl/WxpCV),它使用from google.appengine.api import rdbms,而后者又使用google.storage.speckle.python.api.rdbms_apiproxy,而不是巧妙地使用google.storage.speckle.python.api.rdbms_googleapi不像 Django 驱动程序那样在生产/GAE 实例上 (goo.gl/4ScgJ)。
    • 我正在尝试找到一种方法来更新 mysql+gaerdbms:/// 方言,以根据环境切换使用哪个 API,例如 Django 驱动程序 (if apiproxy_stub_map.apiproxy.GetStub('rdbms'): "use rdbms_apiproxy" else "use rdbms_googleapi")
    • 哦,我无法从我的映射中生成我的架构,即使使用上面的方法也是如此。我得到:sqlalchemy.exc.DatabaseError: (DatabaseError) 1146: Table 'test.users' doesn't exist 'DESCRIBE users' ().
    • 我想我想出了一个方言增强mysql+gaerdbms:///,它可以像Django驱动程序一样与apiproxy和googleapi一起使用。我已经在 SQLALchemy 的 Trak 系统 - sqlalchemy.org/trac/ticket/2649 中提交了一张票以供审核。顺便说一句,方言可以使用create_all() 生成架构,即使我无法使用您的方法。
    猜你喜欢
    • 2013-04-15
    • 2020-09-25
    • 2013-06-15
    • 1970-01-01
    • 2020-03-22
    • 2018-05-05
    • 2021-08-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多