reloader uses "-m" instead of file if possible #1416
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Unfortunately, Python doesn't make the fact that it was run as
python -m module
available, it replaces-m module
with the path to the module insys.argv
. However, Python also has different behavior forpython -m module
vspython file.py
: running a file adds its directory tosys.path
. When the reloader was run withpython -m werkzeug.serving
, it would end up callingpython /path/to/werkzeug/serving.py
on reload, which added/path/to/werkzeug
tosys.path
. This caused import conflicts with module names in Werkzeug shadowing builtins.To determine if
-m
was used, I looked at__main__.__package__
. For all the cases I could think of, it seems that if that's notNone
, then it was run as-m
, otherwise it was run as a file. If we're running as-m
, then the module name can be reconstructed by appending the name of the file insys.argv[0]
to__main__.__package__
.This includes a workaround for Flask's workaround of the previous behavior. Flask currently replaces
sys.argv[0:0]
with["-m", "flask"]
. If Werkzeug sees"-m"
as the first arg it assumes the command line is already correct. This can be removed once Flask depends on the next version of Werkzeug.I tested every combination I could think of on Python 3 and 2, Linux and Windows:
python app.py
python -m app
__main__.py
.python -m app.cli
__main__.py
.python -m werkzeug.serving
python -m flask run
flask run
python2 -m /path/to/app
(without ".py" extension, Python 2 only)Also removed a comment saying not to use relative imports in
werkzeug.serving
(8b2b621), now that we reload with-m
relative imports would work correctly.Closes #461
Closes #531
Closes #593
Closes pallets/flask#2777