Python is a beautiful language syntactically and is also good for readability and maintainability. But when it comes to weaknesses, I think it's biggest drawback is recursive imports.
This weakness stems from the very idea of having
modules for re-usability which no other popular language has to my knowledge. In some like
C#, everything is a class, so this kind of problem never occurs. In others like
PHP, procedural code is allowed but they use the simple
include constructs to add reusable code.
With python, there are many circumstances where X module imports Y and at the same time, the Y module needs to import an object from X. This is a very common scenario once you start developing complex apps. For example, this could be seen even in a very basic
flask app which has its own package (lets say
app), an init module (
__init__.py) and a routes module (
routes.py), something like this:
└───app │ __init__.py │ routes.py
This is a very simple
flask app where I define the actual flask object in the init module:
# c:\source\app\__init__.py from flask import Flask from app import routes app = Flask(__name__)
Now, let me define the routes.py as follows:
# c:\source\app\routes.py from app import app @app.route('/') @app.route('/index') def index(): return "Hello, World"
The problem is that this code won't work! For the simple reason that init module tries to import routes but the routes module will fail (simply because the routes module tries to import the app.app object from init module which hasn't been initialized yet).
This is the problem of recursive import. To fix this, I'll have to ensure that the routes module is always imported after the app object has been initialized as follows:
# c:\source\app\__init__.py from flask import Flask app = Flask(__name__) from app import routes
As you can see, recursive imports can be tricky to deal with in an otherwise structured and seemingly easy language like python.