本文介绍了使用两个名称冲突的 Python 库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用两个 Python 库(Google 的 Cloud Library,以及它们的 Cloud SDK),但它们的名称有冲突(它们都使用 google 在它们的基本导入名称中,并且不在内部使用相对导入).如何在单个应用中使用它们?

更改库的代码以使用正确的相对导入是不切实际的.另外,我知道我可以使用 virtualenv 从单独的 Python 应用程序访问这些库,但是如何从同一个 Python 应用程序中访问它们?

命名冲突详情

以下是有关导入的一些详细信息.当我从云库中导入一个模块时(我运行 import google.cloud.datastore),该库中的另一个导入有一个例外:

>>>导入 libs.google.cloud.datastore回溯(最近一次调用最后一次):文件<console>",第 1 行,在 <module> 中.文件C:[ProjectDIR]libsgoogleclouddatastore\__init__.py",第 52 行,在 <module> 中从 google.cloud.datastore.batch 导入批处理导入错误:没有名为 cloud.datastore.batch 的模块

图书馆正在尝试进行绝对导入,而不是相对导入.谷歌云库无法导入google.cloud.datastore.batch的原因是SDK中已经定义了google,存在命名冲突:

>>>打印 google.__path__['C:\Program Files (x86)\Google\Cloud SDK\google-cloud-sdk\platform\google_appengine\google']

由于云库使用绝对导入,并且SDK中已经定义了名称google,所以导入失败.

解决方案

google 包注意将自己注册为 namespace 包.通过正确设置sys.path这里没有冲突.

您需要正确设置库环境.在项目的根目录中添加一个 appengine_config.py 文件:

来自 google.appengine.ext 导入供应商# 添加安装在lib"文件夹中的任何库.vendor.add('lib')

这会在 sys.path 的正确位置添加 lib 子目录.请参阅安装第三方-在 App Engine 上开发 Python 应用 How-To 中的派对库部分.

从这里开始导入 google.cloud 就可以了:

$ ls -1d lib *.py *.yaml应用程序.yamlappengine_config.py库主文件$ pip install -t lib google-cloud# 安装到lib子目录$ cat main.py导入谷歌从 google.cloud 导入数据存储从 google.appengine.api 导入内存缓存导入 os.path这里 = os.path.dirname(os.path.abspath(__file__))def app(*args, **kwargs):返回 '​​''谷歌:{}<br/>google.cloud.datastore:{}<br/>google.appengine.api.memcache: {}'''.format(os.path.relpath(google.__file__, 这里),os.path.relpath(datastore.__file__, here),os.path.relpath(memcache.__file__, 这里))

并在浏览器中为我提供服务:

google:../google-cloud-sdk/platform/google_appengine/google/__init__.pygoogle.cloud.datastore: lib/google/cloud/datastore/__init__.pycgoogle.appengine.api.memcache:../google-cloud-sdk/platform/google_appengine/google/appengine/api/memcache/__init__.pyc

I want to use two Python libraries (Google's Cloud Library, and their Cloud SDK) in a single application, but they have conflicting names (they both use google in their base import names and do not use relative imports internally). How can I use them in a single app?

Changing the library's code to use proper relative imports is not practical. Also, I know I can use virtualenv to access these libraries from separate python applications, but how do I access them from within the same python app?

Details of the Naming Conflict

Here are some of the details on the import. When I import a module from the Cloud Library (I run import google.cloud.datastore), there is an exception about another import within that library:

>>> import libs.google.cloud.datastore
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "C:[ProjectDIR]libsgoogleclouddatastore\__init__.py", line 52, in <module>
    from google.cloud.datastore.batch import Batch
ImportError: No module named cloud.datastore.batch

The library is trying to do an absolute import, rather than a relative one. The reason that the Google Cloud Library cannot import google.cloud.datastore.batch is because google is already defined in the SDK, there is a naming conflict:

>>> print google.__path__
['C:\Program Files (x86)\Google\Cloud SDK\google-cloud-sdk\platform\google_appengine\google']

Because the Cloud Library uses absolute imports, and the name google is already defined in the SDK, then the import fails.

解决方案

The google packages take care to register themselves as a namespace package. With a properly set up sys.path there is no conflict here.

You need to set up your library environment correctly. Add a appengine_config.py file in the root of your project with:

from google.appengine.ext import vendor

# Add any libraries installed in the "lib" folder.
vendor.add('lib')

This adds the lib subdirectory in the right location of sys.path. See the Installing a third-party library section in the Developing Python Apps on App Engine How-To.

From here on out imports of google.cloud just work:

$ ls -1d lib *.py *.yaml
app.yaml
appengine_config.py
lib
main.py
$ pip install -t lib google-cloud
# installing into the lib subdirectory
$ cat main.py
import google
from google.cloud import datastore
from google.appengine.api import memcache
import os.path

here = os.path.dirname(os.path.abspath(__file__))

def app(*args, **kwargs):
    return '''
google: {}<br />
google.cloud.datastore: {}<br />
google.appengine.api.memcache: {}'''.format(
        os.path.relpath(google.__file__, here),
        os.path.relpath(datastore.__file__, here),
        os.path.relpath(memcache.__file__, here))

and in the browser I am served:

google: ../google-cloud-sdk/platform/google_appengine/google/__init__.py
google.cloud.datastore: lib/google/cloud/datastore/__init__.pyc
google.appengine.api.memcache: ../google-cloud-sdk/platform/google_appengine/google/appengine/api/memcache/__init__.pyc

这篇关于使用两个名称冲突的 Python 库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-18 14:12
查看更多