SQLAlchemy с Google Cloud SQL подключается к серверу разработки

Я использую SQLAlchemy 0.8 с Google App Engine и Cloud SQL. Я хотел бы выполнить полный интеграционный тест локально перед развертыванием, но я не могу заставить SQLAlchemy подключиться к моему серверу разработки MySQL, используя диалект mysql+gaerdbms.

create_engine(
    'mysql+gaerdbms:///test?instance=homingbox:instance1'
)

Я запускаю свой движок приложения из командной строки следующим образом

python dev_appserver.py --mysql_user=username --mysql_password=root ../Source/HomingBox/gae

Всякий раз, когда я пытаюсь попасть в базу данных, я получаю эту прекрасную трассировку стека

ERROR    2013-04-22 21:35:39,987 webapp2.py:1528] (ImportError)  None None
Traceback (most recent call last):
  File "/home/leon/Development/google_appengine/lib/webapp2-2.3/webapp2.py", line 1511, in __call__
    rv = self.handle_exception(request, response, e)
  File "/home/leon/Development/google_appengine/lib/webapp2-2.3/webapp2.py", line 1505, in __call__
    rv = self.router.dispatch(request, response)
  File "/home/leon/Development/google_appengine/lib/webapp2-2.3/webapp2.py", line 1253, in default_dispatcher
    return route.handler_adapter(request, response)
  File "/home/leon/Development/google_appengine/lib/webapp2-2.3/webapp2.py", line 1077, in __call__
    return handler.dispatch()
  File "/home/leon/Development/google_appengine/lib/webapp2-2.3/webapp2.py", line 547, in dispatch
    return self.handle_exception(e, self.app.debug)
  File "/home/leon/Development/google_appengine/lib/webapp2-2.3/webapp2.py", line 545, in dispatch
    return method(*args, **kwargs)
  File "/home/leon/Development/Source/HomingBox/gae/rest.py", line 19, in get_list
    self.response.write(json.dumps(application.get_list()))
  File "/home/leon/Development/Source/HomingBox/gae/dal.py", line 98, in get_list
    return query.all()
  File "/home/leon/Development/Source/HomingBox/gae/sqlalchemy/orm/query.py", line 2140, in all
    return list(self)
  File "/home/leon/Development/Source/HomingBox/gae/sqlalchemy/orm/query.py", line 2252, in __iter__
    return self._execute_and_instances(context)
  File "/home/leon/Development/Source/HomingBox/gae/sqlalchemy/orm/query.py", line 2265, in _execute_and_instances
    close_with_result=True)
  File "/home/leon/Development/Source/HomingBox/gae/sqlalchemy/orm/query.py", line 2256, in _connection_from_session
    **kw)
  File "/home/leon/Development/Source/HomingBox/gae/sqlalchemy/orm/session.py", line 797, in connection
    close_with_result=close_with_result)
  File "/home/leon/Development/Source/HomingBox/gae/sqlalchemy/orm/session.py", line 801, in _connection_for_bind
    return self.transaction._connection_for_bind(engine)
  File "/home/leon/Development/Source/HomingBox/gae/sqlalchemy/orm/session.py", line 297, in _connection_for_bind
    conn = bind.contextual_connect()
  File "/home/leon/Development/Source/HomingBox/gae/sqlalchemy/engine/base.py", line 1669, in contextual_connect
    self.pool.connect(),
  File "/home/leon/Development/Source/HomingBox/gae/sqlalchemy/pool.py", line 272, in connect
    return _ConnectionFairy(self).checkout()
  File "/home/leon/Development/Source/HomingBox/gae/sqlalchemy/pool.py", line 425, in __init__
    rec = self._connection_record = pool._do_get()
  File "/home/leon/Development/Source/HomingBox/gae/sqlalchemy/pool.py", line 855, in _do_get
    return self._create_connection()
  File "/home/leon/Development/Source/HomingBox/gae/sqlalchemy/pool.py", line 225, in _create_connection
    return _ConnectionRecord(self)
  File "/home/leon/Development/Source/HomingBox/gae/sqlalchemy/pool.py", line 318, in __init__
    self.connection = self.__connect()
  File "/home/leon/Development/Source/HomingBox/gae/sqlalchemy/pool.py", line 368, in __connect
    connection = self.__pool._creator()
  File "/home/leon/Development/Source/HomingBox/gae/sqlalchemy/engine/strategies.py", line 80, in connect
    return dialect.connect(*cargs, **cparams)
  File "/home/leon/Development/Source/HomingBox/gae/sqlalchemy/engine/default.py", line 279, in connect
    return self.dbapi.connect(*cargs, **cparams)
  File "/home/leon/Development/google_appengine/google/storage/speckle/python/api/rdbms_googleapi.py", line 183, in __init__
    super(GoogleApiConnection, self).__init__(*args, **kwargs)
  File "/home/leon/Development/google_appengine/google/storage/speckle/python/api/rdbms.py", line 810, in __init__
    self.OpenConnection()
  File "/home/leon/Development/google_appengine/google/storage/speckle/python/api/rdbms.py", line 832, in OpenConnection
    self.SetupClient()
  File "/home/leon/Development/google_appengine/google/storage/speckle/python/api/rdbms_googleapi.py", line 193, in SetupClient
    self._client = RdbmsGoogleApiClient(**kwargs)
  File "/home/leon/Development/google_appengine/google/storage/speckle/python/api/rdbms_googleapi.py", line 106, in __init__
    rdbms.OAUTH_CREDENTIALS_PATH)
  File "/usr/lib/python2.7/posixpath.py", line 268, in expanduser
    import pwd
  File "/home/leon/Development/google_appengine/google/appengine/tools/devappserver2/python/sandbox.py", line 827, in load_module
    raise ImportError

Любая помощь высоко ценится


person Leon    schedule 22.04.2013    source источник
comment
у вас установлен домашний каталог?   -  person MichaelJCox    schedule 23.04.2013


Ответы (1)


Вот моя гипотеза, основанная на трассировке стека: когда приложение не может найти ваш домашний каталог, оно пытается импортировать pwd и таким образом получить информацию о домашнем каталоге. Приложение пытается вызвать этот фрагмент кода в posixpath.py:

if 'HOME' not in os.environ:
        import pwd
        userhome = pwd.getpwuid(os.getuid()).pw_dir
    else:
        userhome = os.environ['HOME']

Кроме того, я не думаю, что GAE позволит импортировать pwd из соображений безопасности. Среда песочницы не выглядит включенной в белый список разрешенных модулей и поднимает ImportError, если модулей нет в этом списке.

Если я попытаюсь просто выполнить import pwd внутри обычного модуля-обработчика, GAE этого не допустит.

person MichaelJCox    schedule 23.04.2013
comment
Итак, если я правильно понимаю, то, что я пытаюсь сделать, на самом деле невозможно из-за того, почему gae ограничивает некоторые функции Python? - person Leon; 23.04.2013
comment
Установлена ​​ли какая-либо переменная среды HOME? Если это не так, установите его и посмотрите, поможет ли это (или, по крайней мере, выдаст другую ошибку). - person MichaelJCox; 24.04.2013
comment
На самом деле похоже, что os.environ['HOME'] не существует в среде GAE. os.environ загружается с переменными среды GAE. - person MichaelJCox; 24.04.2013
comment
Насколько это невозможно... Я не знаю, атм. Возможно, вы захотите попытаться выяснить, почему вызывается этот код, и посмотреть, есть ли способ обойти это. - person MichaelJCox; 24.04.2013
comment
Спасибо, Майкл. Честно говоря, теперь это становится полным излишеством для тестов, которые я хочу запустить. Кажется разумным использовать стандартный диалект MySQL, а не возиться с App Engine. Я все еще принимаю ваш ответ, так как он действительно помог мне лучше понять Google App Engine. - person Leon; 24.04.2013