Pylint plugin to detect blocking calls in async functions
Project description
Pylint Blocking Calls Checker
This is a pylint plugin that checks for blocking calls in your async python code.
Installation
The best way to install the plugin is to use pip as follows:
pip install pylint-blocking-calls
Usage
Let's start with an example:
import asyncio
import time
def blocking_function():
time.sleep(5) # an example of a IO-bound operation
async def async_function():
blocking_function() # <- This call blocks the event loop!
def some_another_function():
blocking_function()
async def async_function2():
some_another_function() # <- This call also implicitly blocks the event loop.
async def main():
time_before = time.time()
await asyncio.gather(async_function(), async_function2())
time_after = time.time()
# This can take 5 seconds but actually takes 10, because both async functions block the event loop
print(f"Time elapsed: {(time_after - time_before):.0f} seconds")
if __name__ == "__main__":
asyncio.run(main())
Save the file with the name "example.py" and run the following command:
BLOCKING_FUNCTION_NAMES="^blocking_function$" pylint --load-plugins=pylint_blocking_calls example.py
This should provide the following output:
************* Module example
example.py:9:4: W0002: blocking_function (blocking-call)
example.py:17:4: W0002: some_another_function -> blocking_function (blocking-call)
Plugin configuration
Plugin supports configuration via the following environment variables:
# required
export BLOCKING_FUNCTION_NAMES="" # comma-separated list of regexps that match blocking function names in your project
# optional
export SKIP_FUNCTIONS="" # comma-separated list of regexps that match function names that should be skipped
export SKIP_MODULES="" # comma-separated list of regexps that match module names that should be skipped
export SKIP_DECORATED="" # comma-separated list of regexps that match decorator names that should be skipped
See the tests/test_blocking_calls.py file for a real configuration example.
Production setup
The plugin is designed to be used in a CI/CD pipeline.
NOTE: When running on a multiple files, you must run pylint with the single process mode (
--jobs=1
), otherwise there could be a race condition and the plugin may be not working correctly.
Consider the following workaround in production:
# ... as a part of your CI/CD pipeline
export BLOCKING_FUNCTION_NAMES="...."
export SKIP_FUNCTIONS="...."
export SKIP_MODULES="...."
export SKIP_DECORATED="...."
# run pylint with multiple cores for better performance
pylint --disable=blocking-call $(REPO_DIR)/src
# run pylint with a single core to check for blocking calls
pylint -j 1 --disable=all --enable=blocking-call $(REPO_DIR)/src
Motivation
This plugin was created to help us find blocking calls in our async code.
We use it in our CI pipeline to prevent blocking calls from being merged into the master branch.
Please share your feedback and ideas in the issues section.
External links
View the plugin page on PyPi.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file pylint-blocking-calls-0.1.0.tar.gz
.
File metadata
- Download URL: pylint-blocking-calls-0.1.0.tar.gz
- Upload date:
- Size: 6.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.1.15 CPython/3.11.0 Darwin/21.6.0
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 9dae7dc23213c9328c9b3917df1209107dc225b881444c92c9dffe4cac24c817 |
|
MD5 | a3e86270fa3bbde07bd901ccd6fc0de6 |
|
BLAKE2b-256 | 421ec5e1fa4a7f97fe311184dcbe4dde6fe7839342aba4847484187f32bfb5fa |
File details
Details for the file pylint_blocking_calls-0.1.0-py3-none-any.whl
.
File metadata
- Download URL: pylint_blocking_calls-0.1.0-py3-none-any.whl
- Upload date:
- Size: 6.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.1.15 CPython/3.11.0 Darwin/21.6.0
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 373abefd8a699d835f74708fe8600d3432a35c01646a7581510f3b0c8b99f7d7 |
|
MD5 | 9338d9916c3385fec2ec70dffc3b070e |
|
BLAKE2b-256 | abfd76d475ab5c0cf7685ea7dbfa9fd6c35529c5b9483483ec83afb435f61045 |