Unable to connect to Google Cloud SQL from development server using SQLAlchemy

匿名 (未验证) 提交于 2019-12-03 01:05:01

问题:

I've been unsuccessful at connecting to Google Cloud SQL using SQLAlchemy 0.7.9 from my development workstation (in hopes to generate the schema using create_all()). I can't get passed the following error:

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

I was able to successfully connect to the database instance using the google_sql.py instancename, which initially opened up a browser to authorize the connection (which now appears to have cached the authorization, although I don't have the ~/Library/Preferences/com.google.cloud.plist file as https://developers.google.com/cloud-sql/docs/commandline indicates I should)

Here is the simple application I'm using to test the connection:

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

The full stacktrace is available here - https://gist.github.com/4486641

回答1:

It turns out the mysql+gaerdbms:/// driver in SQLAlchemy was only setup to use the rdbms_apiproxy DBAPI, which can only be used when accessing Google Cloud SQL from a Google App Engine instance. I submitted a ticket to SQLAlchemy to update the driver to use the OAuth-based rdbms_googleapi when not on Google App Engine, just like the Django driver provided in the App Engine SDK. rdbms_googleapi is also the DBAPI that google_sql.py uses (remote sql console).

The updated dialect is expected to be part of 0.7.10 and 0.8.0 releases, but until they are available, you can do the following:


1 - Copy the updated dialect in the ticket to a file (ex. 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:///?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 - Register the custom dialect (you can override the existing schema)

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

Note: 0.8 allows a dialect to be registered within the current process (as shown above). If you are running an older version of SQLAlchemy, I recommend upgrading to 0.8+ or you'll need to create a separate install for the dialect as outlined here.


3 - Update your create_engine('...') url as the project and instance are now provided as part of the query string of the URL

mysql+gaerdbms:///?instance=

for example:

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


回答2:

I think I have a working sample script as follows. Can you try a similar thing and let me know how it goes?

However(and you might be already aware of it), if your goal is to create the schema on Google Cloud SQL instance, maybe you can create the schema against a local mysql server, dump it with mysqldump, and then import the schema to Google Cloud SQL. Using local mysql server is very convenient for development anyway.

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() 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!