导入错误:不允许从用户应用程序代码导入开发应用服务器沙盒模块



我正在开发一个用Python(标准环境(编写的Google App Engine应用程序,我需要将开发服务器环境中的一些其他模块列入白名单。

我已经在 appengine_config 文件中使用此代码很长时间了,并且效果很好:

from google.appengine.tools.devappserver2.python import sandbox
sandbox._WHITE_LIST_C_MODULES += ['_ssl', '_socket']

正如这个问题所回答的,前段时间谷歌云SDK更新了,之前的导入导致了导入错误。导入只需更改为:

from google.appengine.tools.devappserver2.python.runtime import sandbox

通过此更改,一切再次运行良好,直到我将 Cloud SDK 更新到版本:186.0.0。

现在似乎有一个"SandboxAccessPreventionImportHook"类已添加到沙盒模块中,因此无法从App Engine应用程序导入。这是应用程序引发的错误:

ImportError: Importing the devappserver sandbox module (google.appengine.tools.devappserver2.python.runtime.sandbox) from user application code is not permitted.

有没有人知道如何绕过它?还是有另一种方法可以将开发服务器环境中的模块列入白名单?

谢谢!!!

我们遇到了与 OP 完全相同的问题,但不幸的是 Alex 的解决方案对我们不起作用。

虽然这是一个非常非常黑客的解决方案,但这正是对我们有用的。请注意,沙盒的修改必须在更新后重做。

sandbox.py 修改位于 {appengine_sdk_dir}/google/appengine/tools/devappserver2/python/runtime/sandbox.py并将 Alex 的第一个示例中的_ssl_socket添加到_WHITE_LIST_C_MODULES列表中。

_WHITE_LIST_C_MODULES = [
    // keep existing items
    '_ssl',
    '_socket'
]

然后,我们从appengine_config.py中删除了导入和沙盒覆盖。

vendor.add('lib')
if os.environ.get('SERVER_SOFTWARE', '').startswith('Development'):
    import imp
    import os.path
    import inspect
    # Use the system socket.
    real_os_src_path = os.path.realpath(inspect.getsourcefile(os))
    psocket = os.path.join(os.path.dirname(real_os_src_path), 'socket.py')
    imp.load_source('socket', psocket)
# handle requests_toolbelt's monkeypatch as you see fit.

让我们希望有一天不再需要这样做!

上下文

所以对我来说,这个问题的根源是dev_appserver.py无法发送出站https请求/套接字。

然后的解决方案是把它放在我的appengine_config.py

vendor.add('lib')
if os.environ.get('SERVER_SOFTWARE', '').startswith('Development'):
    import imp
    import os.path
    import inspect
    try:
        from google.appengine.tools.devappserver2.python import sandbox
    except ImportError:
        from google.appengine.tools.devappserver2.python.runtime import sandbox
    sandbox._WHITE_LIST_C_MODULES += ['_ssl', '_socket']
    # Use the system socket.
    real_os_src_path = os.path.realpath(inspect.getsourcefile(os))
    psocket = os.path.join(os.path.dirname(real_os_src_path), 'socket.py')
    imp.load_source('socket', psocket)
else:
    # Doing this on dev_appserver/localhost seems to cause outbound https requests to fail
    import requests
    from requests_toolbelt.adapters import appengine as requests_toolbelt_appengine
    # Use the App Engine Requests adapter. This makes sure that Requests uses
    # URLFetch.
    requests_toolbelt_appengine.monkeypatch() 

今天我升级了我的云 sdk 并开始获得

ImportError: Importing the devappserver sandbox module (google.appengine.tools.devappserver2.python.runtime.sandbox) from user application code is not permitted.

如果我删除_WHITE_LIST_C_MODULES的东西,那么在使用python请求库发出出站https请求时会出现此错误:

  File "/Users/alexindaco/google-cloud-sdk/platform/google_appengine/google/appengine/api/urlfetch.py", line 293, in fetch
    return rpc.get_result()
  File "/Users/alexindaco/google-cloud-sdk/platform/google_appengine/google/appengine/api/apiproxy_stub_map.py", line 613, in get_result
    return self.__get_result_hook(self)
  File "/Users/alexindaco/google-cloud-sdk/platform/google_appengine/google/appengine/api/urlfetch.py", line 413, in _get_fetch_result
    rpc.check_success()
  File "/Users/alexindaco/google-cloud-sdk/platform/google_appengine/google/appengine/api/apiproxy_stub_map.py", line 579, in check_success
    self.__rpc.CheckSuccess()
  File "/Users/alexindaco/google-cloud-sdk/platform/google_appengine/google/appengine/api/apiproxy_rpc.py", line 157, in _WaitImpl
    self.request, self.response)
  File "/Users/alexindaco/google-cloud-sdk/platform/google_appengine/google/appengine/ext/remote_api/remote_api_stub.py", line 222, in MakeSyncCall
    self._MakeRealSyncCall(service, call, request, response)
  File "/Users/alexindaco/google-cloud-sdk/platform/google_appengine/google/appengine/ext/remote_api/remote_api_stub.py", line 241, in _MakeRealSyncCall
    request_pb.set_request(request.Encode())
  File "/Users/alexindaco/google-cloud-sdk/platform/google_appengine/google/net/proto/ProtocolBuffer.py", line 103, in Encode
    self.Output(e)
  File "/Users/alexindaco/google-cloud-sdk/platform/google_appengine/google/net/proto/ProtocolBuffer.py", line 347, in Output
    self.OutputUnchecked(e)
  File "/Users/alexindaco/google-cloud-sdk/platform/google_appengine/google/appengine/api/urlfetch_service_pb.py", line 481, in OutputUnchecked
    out.putDouble(self.deadline_)
  File "/Users/alexindaco/google-cloud-sdk/platform/google_appengine/google/net/proto/ProtocolBuffer.py", line 592, in putDouble
    a.fromstring(struct.pack("<d", v))
error: required argument is not a float 

然后我在这个问题中找到了堆栈跟踪https://github.com/requests/requests/issues/4078这似乎表明这仅在 python-requests 版本 2.16.0 之后才开始发生

溶液

我所有的第三方库都安装到我的项目根目录中一个名为 lib 的文件夹中,使用

pip install -t lib

现在,我有liblocalhost_libs,我做到了:

pip install -t localhost_libs requests==2.16

我的appengine_config.py现在有这个:

vendor.add('lib')
if os.environ.get('SERVER_SOFTWARE', '').startswith('Development'):
    vendor.add('localhost_libs')
    import pkg_resources
    pkg_resources.require("requests==2.16.0")
import requests
print "requests.__version__", requests.__version__
from requests_toolbelt.adapters import appengine as requests_toolbelt_appengine
# Use the App Engine Requests adapter. This makes sure that Requests uses
# URLFetch.
requests_toolbelt_appengine.monkeypatch()
print "Appengine config done"

编辑:修改的解决方案以使用pkg_resources,不需要prod_libs文件夹

沙盒模块的位置已移动到运行时模块中。

from google.appengine.tools.devappserver2.python import runtime
runtime.sandbox._WHITE_LIST_C_MODULES += ['_ssl', '_socket']

@karloskar提到的方式解决了我的情况。

但是,在我修改 sandbox.py 以允许WHITE_LIST_ssl和_socket后,我遇到了另一个库导入问题 - 导入错误:没有名为google.auth的模块

对于谁也得到了上面的google.auth导入错误,您可以考虑像下面这样更新您的appengine_config.py。这就是解决我的导入问题的方法。

# appengine_config.py
import os
import google
from google.appengine.ext import vendor
lib_directory = os.path.dirname(__file__) + '/lib'
# Change where to find the google package (point to the lib/ directory)
google.__path__ = [os.path.join(lib_directory, 'google')] + google.__path__
# Add any libraries install in the "lib" folder.
vendor.add(lib_directory)

参考文献1:App Engine 在 dev_appserver.py 中找不到 google.auth 文件

参考文献2:https://github.com/GoogleCloudPlatform/google-auth-library-python/issues/169#issuecomment-315417916

最新更新