无法从子文件夹的__init__中导入

3
这是我的文件夹结构:
storage/
    __init__.py - contains class StorageAbstract, class DummyStorage, class STORE_TYPE
    file.py - contains class FileStorage
    db/
        __init__.py - contains class DbStorage, class DbStorageAbstract 
        pg.py - contains class PgStorage
        sqlite.py - contains class SQLiteStorage

Classes PgStorage(Pg 存储)和 SQLiteStorage(SQLite 存储)继承自 DbStorageAbstract(抽象数据库存储),所以我需要导入它。我像这样执行导入操作(在 pg.py 和 sqlite.py 中):

from . import DbStorageAbstract

这将导致以下错误:

ImportError: cannot import name 'DbStorageAbstract'

然而,当我将DbStorageAbstract从storage/db/__init__py移动到storage/__init__py并像这样导入它时:
from .. import DbStorageAbstract

然后它就可以正常工作了。我已经阅读过这个这个以及许多其他资源,但仍然无法弄清楚是什么导致了问题。如果出现循环依赖,那么将类移到另一个文件中也不会有帮助,我想。

如果需要更多信息,请在评论中告诉我,我会编辑问题。

我正在使用Python 3.5

编辑:

尽管此问题已被确定为此问题的可能重复项,但我不知道它如何回答我的问题。与其他问题不同,我已经在每个文件夹中有init文件。如果我错了,请指出我可以找到答案的位置。

编辑2: 这是db/init.py文件:

##################################################################
# Copyright 2018 Open Source Geospatial Foundation and others    #
# licensed under MIT, Please consult LICENSE.txt for details     #
##################################################################

#import sys
#sys.path.append("/mnt/c/Users/Jan/Documents/GitHub/pywps")

import logging
from abc import ABCMeta, abstractmethod
from pywps import configuration as config
from .. import StorageAbstract
from . import sqlite
from . import pg


LOGGER = logging.getLogger('PYWPS')


class DbStorageAbstract(StorageAbstract):
    """Database storage abstract class
    """

    __metaclass__ = ABCMeta

    @abstractmethod
    def store(self, output):

        pass


    @abstractmethod
    def store_output(self, file_name, identifier):

        pass


class DbStorage(StorageAbstract):

    def __init__(self):

       self.storage = self.get_db_type()


    def store(self, output):

        assert(self.storage is not None)
        self.storage.store(output)


    def get_db_type(self):
        # get db_type from configuration 
        try:
            db_type = config.get_config_value('db', 'db_type')
        except KeyError:
            raise exception("Database type has not been specified")

        # create an instance of the appropriate class
        if db_type == "PG":
            storage = pg.PgStorage()
        elif db_type == "SQLITE":
            storage = sqlite.SQLiteStorage()
        else:
            raise exception("Unknown database type: '{}'".format(db_type))

        return storage
2个回答

3

导入操作发生在类定义之前。在db/__init__.py中,您正在导入依赖于此处定义的类的pg.py, sqlite.py。为解决此问题,请将DbStorageAbstract移动到另一个文件中,并且如果您要在与pg.py,sqlite.py相同的文件中使用它,则确保导入方式如下:

from . import dbstorage # this file is the new one contains DbStorageAbstract class
from . import pg, sqlite

请注意,如果两个模块相互依赖,请尝试创建第三个模块来解决此问题。

1
我认为你应该在子目录中创建另一个文件。
storage/
    __init__.py - contains class StorageAbstract, class DummyStorage, class STORE_TYPE
    file.py - contains class FileStorage
    db/
        __init__.py - 
        pg.py - contains class PgStorage
        sqlite.py - contains class SQLiteStorage
        base.py contains class DbStorage, class DbStorageAbstract

然后,pg.py 文件和 sqlite.py 文件将会导入如下的类:

from base import DbStorageAbstract

而且__init__.py文件也应该是这样的

from base import DbStorageAbstract,  DbStorageAbstract

不确定这是否是最符合Python风格的方式,可能这也会对您有所帮助:https://dev59.com/kXRB5IYBdhLWcg3wkIBN - Nicolò Gasparini
是的,我同意你提出的建议可能有效,但我正在尽量减少文件数量,所以创建另一个文件恰恰是我不想做的事情(除非有必要)。 - Jan Pisl
你能不能不使用完整路径来导入呢?从storage.db中导入DbStorageAbstract应该可以工作。 - Nicolò Gasparini

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接