Reputation: 39826
I have 2 classes (GraphQL type definitions) that depend on each other. I would like to move them to separate files.
As long as they are defined in the same file, no problems.
# all_schemas.py
class AuthorSchema(graphene.ObjectType):
publications = graphene.List(lambda: PublicationSchema)
class PublicationSchema(graphene.ObjectType):
author = graphene.Field(AuthorSchema)
As soon as I put them into separate files, I run into the 'circular import' issue.
author_schema.py
from publication_schema import PublicationSchema
class AuthorSchema(graphene.ObjectType):
publications = graphene.List(lambda: PublicationSchema)
publication_schema.py
from author_schema import AuthorSchema
class PublicationSchema(graphene.ObjectType):
author = graphene.Field(AuthorSchema)
Here's what the error that I believe to show the circular import issue:
from author_schema import AuthorSchema
File "models/author_schema.py", line 1, in <module>
from publication_schema import PublicationSchema
File "models/publication_schema.py", line 2, in <module>
from author_schema import AuthorSchema
ImportError: cannot import name AuthorSchema
What are my options for solving this issue?
Some people said that circular imports are bad practice, I don't see why this would be the case here, but I would like to learn why. They also suggest to refactor the code, but I'm wondering how to do that exactly, without ending up with one huge file which contain all interdependent classes.
(Note that I'm using Python 2.7, on google app engine)
Upvotes: 3
Views: 2093
Reputation: 25779
The above comment standing, if you really, really have to do this (and you don't!) you can always use delayed import in your AuthorSchema
:
def get_publication_schema():
from publication_schema import PublicationSchema
return PublicationSchema
class AuthorSchema(graphene.ObjectType):
publications = graphene.List(get_publication_schema)
The caveat - you still won't be able to execute any of the code that calls PublicationSchema
from the 'global' space of autor_schema.py
as both files need to be fully loaded in order to reference one another. But in third-party usage scenario this will work.
Upvotes: 1
Reputation: 29071
The standard python trick to avoid circular dependencies,is to avoid them running at import time. Instead of putting. For example, put from author_schema import AuthorSchema
inside the PublicationSchema
class, so it does not run at the time this class is imported from AuthorSchema
. However, this is unstable, the exact point to put them depends on the code and might change as the code changes.
The standard OOP approach is to for a AuthorInterface
, that the publication imports and the author implements. See acyclic dependencies principle and dependency inversion principle.
Upvotes: 1