Python,模块<>模块,如何避免循环导入。

3

假设我有一个pydantic模型(它可以是任何类型的),应该知道如何将自己转换为orm(它可以是任何类型的)模型。 为此,我构建了mod_a.py:

from pydantic import BaseModel

from mod2mod.mod_b import DBUser

class User(BaseModel):

    name: str
    surname: str

    def to_orm(self) -> DBUser:
        return DBUser(
            full_name = f"{self.surname},{self.name}"
        )

我希望我的ORM模型能够转化为pydantic模型,因此我的mod_b.py如下所示:
from sqlalchemy.orm import declarative_base
from sqlalchemy import Column, Integer, String
from mod_a import User

Base = declarative_base()

class DBUser(Base):
    __tablename__ = 'users'

    id = Column(Integer, primary_key=True)
    full_name = Column(String)

    def to_pydantic(self) -> User:
        surname, name = self.full_name.split(',')
        User(
            name=name,
            surname=surname
        )

这个想法是能够像在mod2mod.py中一样随意切换模型:

import pydantic
from mod_a import User
from mod_b import DBUser


user = User(name='John', surname='Doe')
orm_user = user.to_orm()

pydantic_user = orm_user.to_pydantic()

print(user)
print(pydantic_user)

显然这种方法行不通,原因是:
ImportError: cannot import name 'User' from partially initialized module 'mod_a' (most likely due to a circular import) (/mod2mod/mod_a.py)

如何解决这种问题? 我需要另一个实体来处理模型之间的转换并将当前模型方法放在那里吗?还是有其他设计模式可用?
2个回答

3
你可以使用import ...的方式,而不是from ... import ...的方式。并且将返回类型提示用引号括起来(我在下面做了这样的操作),或者使用延迟注释评估PEP-563(顺便说一句,它是Python 3.10的默认设置)。
# mod_a.py
from pydantic import BaseModel
import mod_b


class User(BaseModel):
    name: str
    surname: str

    def to_orm(self) -> 'mod_b.DBUser':
        return mod_b.DBUser()

# mod_b.py
import mod_a

class DBUser:
    def to_pydantic(self) -> 'mod_a.User':
        return mod_a.User(
            name="",
            surname=""
        )

这正是我所需要的。谢谢@alex_noname。 - user3225309

1

你需要进行本地 import 并使用 TYPE_CHECKING 来实现类型提示。

from typing import TYPE_CHECKING
from pydantic import BaseModel

if TYPE_CHECKING:
    from mod2mod.mod_b import DBUser
    

class User(BaseModel):

    name: str
    surname: str

    def to_orm(self) -> "DBUser":
        from mod2mod.mod_b import DBUser

        return DBUser(
            full_name = f"{self.surname},{self.name}"
        )

同样对 DBUser 进行此操作。


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