I do a lot of Python programming nowadays. Python has nice libraries such as NumPy and Pandas, but one annoyance is running a Python script that may run for minutes and then crash with a message
name 'foo' undefined
This does not happen in Fortran with implicit none and proper compiler options. I have found it helpful to create a wrapper around the python command that first runs the tools ruff and vulture on a Python script to find bugs and only runs the script if no bugs are found. Ruff is a linter, and vulture finds unused variables.
What tools do you use for Python that confer some of the benefits of a compiled language such as Fortran?
I used mypy for a while, but wasn’t happy with it. Cython and Nuitka are compilers, so they also check Python code more thoroughly than the interpreter.
Having had that exact same problem with a large, full-stack, Python app, I wanted to share a project setup that might might align perfectly with your needs.
Key features include static type analysis and linting with mypy and ruff, flake8, pylint (there is some good overlap between these three), formatting with ruff, testing framework with pytest and coverage, and lastly pre-commit hooks that automate the execution of all* of the above.
The added VS Code integration through config files allows for a plug-and-play experience. Simply opening the project in VS Code will start all related linter and checker extensions.
The configuration for the linters is fairly strict. For mypy I’ve opted for a gradual approach, by disabling the more opinionated checks.
I think the most important change in code style will be the “type hinting” integration. I’ve seen a lot of pushback in academia, especially from the “old” Python guard. Personally, I’ve come to love it (and rely on it) as I do Fortran’s type checking. Let me know if I can help further.
(p.s I also have a sister repository for Fortran with the same premise, that integrates much of the Python project.)
They all used to be integrated in the ms-python.python extension, but recently Microsoft fully embraced their plugin architecture so every tool (flake8, isort, pylint, etc.) has its own official extension. These tend to work well for me and my team:
ms-python.black-formatter
ms-python.flake8 (with a rule exclusion in .flake8 or setup.cfg)
ms-python.isort
ms-python.vscode-pylance
ms-python.pylint
ms-python.debugpy
pre-commit config hooks also look quite similar, e.g. see fortls’ setup.
@MattAl I’ve heard great things for ruff, but have not had the chance to use it yet. Other than speed are there any compelling reasons to swap black+flake8+isort+pyupgrade with ruff?
ms-python.python still includes ms-python.vscode-pylance and ms-python.debugpy as (optional) dependencies, and will automatically install and use them. Pylance does a lot of heavy lifting and is pretty good.
@gnikit Hmm, it’s difficult to say. I’ll try not to repeat what astral claims.
Not swapped yet: I do install and use the flake8 and pylint extensions along side ruff for A/B testing.
Performance can be its own reason: Running VS Code locally is in most cases a different experience than running over an SSH connection (which I very regularly do). In those cases, all extensions are running on some kind of server frontend, sharing resources with tens of others. Very often I can see the linters working through a live changeset for several seconds before I get feedback. One to two orders of magnitude difference can be expected if only ruff is linting.
One vs Many: ruff wants to integrate rules from across all major Python linters, including rules from Pyflakes, pycodestyle, pylint, flake8, isort, pyupgrade (and several more niche ones). As a bonus, they’ve got some of their own unique checks too. The integration is not finished, and can be tracked here for each rule independently. I’m guessing the 80/20 rule applies a lot.
One vs Many take 2: It also integrates formatting, and is supposed to be a drop-in replacement for black.
A/B testing results: Running them in parallel showcases that it’s not ready for primetime yet, but it’s not-so-slowly getting there. Anecdotally, in my case, flake8 reports parity while pylint has a few issues marked with a 9.86 score (I actively ignore 14 out of 19).