The Blackfire Python SDK is available with the Blackfire Python Package.
The Blackfire Python SDK allows you to generate profiles from your own code and eases the integration with third-party libraries.
The main entry point of the SDK is the blackfire
module:
1 | from blackfire import probe
|
The probe allows you to profile any parts of your code:
1 2 3 4 5 6 7 8 | from blackfire import probe
probe.initialize()
probe.enable()
# some Python code you want to profile
probe.end()
|
The Blackfire Probe is usually configured via environment variables, but you can customize the configuration when calling
the initialize()
method via optional parameters:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | from blackfire import probe
probe.initialize(
# Client credentials. If None, they are read from environment variables, or config_file.
client_id=None,
client_token=None,
# 1: error, 2: warning, 3: info, 4: debug
log_level=None,
# The destination of the log. i.e: /tmp/probe.log
log_file=None,
# Where to find the Blackfire CLI configuration file to retrieve the client_id and client_token values.
config_file='~/.blackfire.ini',
# The Blackfire Query, usually given by blackfire run or created on the fly by the SDK.
query=None,
# The network socket to use for contacting the agent
agent_socket=None,
# The connection timeout when connecting to the agent
agent_timeout=None,
# The Blackfire API endpoint
endpoint=None,
)
|
The SDK provides the run(call_end=True)
method that simplifies the use of the
enable()
and disable()
methods:
1 2 3 4 5 | from blackfire import probe
with probe.run():
foo()
bar()
|
is equivalent to:
1 2 3 4 5 6 7 8 9 | from blackfire import probe
probe.enable()
try:
foo()
bar()
finally:
probe.disable()
probe.end() # if call_end is True.
|
The SDK provides the @profile
decorator, making it possible to profile
functions separately:
1 2 3 4 5 6 7 8 | from blackfire import profile
@profile
def foo():
import time
time.sleep(1.0)
foo()
|
In the snippet above, function foo()
is using the @profile
decorator.
A probe instance is created by the decorator, using the configuration defined
by environment variables.
You may specify a pair of Client ID/Token in the decorator:
1 2 3 4 5 6 7 8 | from blackfire import profile
@profile(client_id = "my_client_id", client_token = "my_client_token")
def foo()
import time
time.sleep(1.0)
foo()
|
1 2 3 | from blackfire import probe
probe.initialize()
|
Start profiling the code by calling enable()
:
1 2 | # Start the profiling
probe.enable()
|
Stop profiling the code by calling disable()
:
1 2 | # Stop the profiling
probe.disable()
|
You can call enable()
and disable()
as many times as needed in your
code. You can also discard any collected data by calling clear_traces()
.
Calling end()
instead of disable()
stops the profiling and forces the
collected data to be sent to Blackfire:
1 2 3 | # Stop the profiling
# Send the result to blackfire
probe.end()
|
Thanks to the Distributed Profiling feature, you can embed sub-profiles in a main profile.
For instance, when profiling command line programs that call sub-processes, you might want to trigger profiles for them as well. You can do so by generating a sub-profile request:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | import subprocess
import sys
import os
from blackfire import probe
probe.initialize(
client_id='xxxx',
client_token='xxxx'
)
with probe.run():
env = os.environ.copy()
env['BLACKFIRE_QUERY'] = probe.generate_subprofile_query()
_ = subprocess.run([sys.executable, "my_subprocess.py"], env=env)
|
Sub-profiles also work for HTTP requests by adding a X-Blackfire-Query
HTTP
header.
1 2 3 4 5 6 7 | import requests
from blackfire import probe
with probe.run():
url = 'https://mycustomapi.com'
headers = {'X-Blackfire-Query:': probe.generate_subprofile_query()}
r = requests.get(url, headers=headers)
|
Note
The target process or HTTP server being sub-profiled may be written in any language supported by Blackfire.
With Markers, you can add cue-points to the Timeline View. This can be done by adding the following instruction in your code, where you want to add such a cue-point:
1 2 | from blackfire import probe
probe.add_marker('My Marker Label')
|