Wrapper Classes

This section describe the three wrapper classes that are provided by this Python package. In most cases, you should be able to just grab one of them and implement a few callbacks or overrides some methods in your subclasses to interact with the Austin binary.

If you want to make your own implementation of the wrapper, the austin.BaseAustin abstract base class can provide you with a good starting point.

Note

For the wrappers to work as expected, the Austin binary needs to be locatable from the following sources, in the given order

  • current working directory;

  • the AUSTINPATH environment variable which gives the path to the folder that contains the Austin binary;

  • the .austinrc TOML configuration file in the user’s home folder, e.g. ~/.austinrc on Linux (see below);

  • the PATH environment variable.

The Abstract Austin Base Class

class austin.BaseAustin(sample_callback=None, ready_callback=None, terminate_callback=None)

Base Austin class.

Defines the general API that abstract Austin as an external process. Subclasses should implement the start() method and either define the on_sample_received() method or pass it via the constructor. Additionally, the on_ready() and the on_terminate() methods can be overridden or passed via the constructor to catch the corresponding events. Austin is considered to be ready when the first sample is received; it is considered to have terminated when the process has terminated gracefully.

If an error was encountered, the AustinError exception is thrown.

BINARY = 'austin'
BINARY_VERSION = (3, 0, 0)
binary_path

Discover the path of the Austin binary.

Lookup order is: - current working directory - AUSTINPATH variable - ~/.austinrc file - PATH variable.

check_exit(rcode, stderr)

Check Austin exit status.

Return type

None

check_version()

Check for the minimum Austin binary version.

Return type

None

get_child_process()

Get the child process.

Return an instalce of psutil.Process representing the (main) process being profiled by Austin at the OS level.

Return type

Process

get_command_line()

Get the inferred command line.

Return the command line of the (main) process that is being profiled by Austin.

Return type

Optional[str]

get_process()

Get the underlying Austin process.

Return an instance of psuitl.Process that can be used to control the underlying Austin process at the OS level.

Return type

Process

is_running()

Determine whether Austin is running.

Return type

bool

on_ready(process, child_process, command_line, data=None)

Ready event callback.

Implement to get notified when Austin has successfully started or attached the Python process to profile and the first sample has been produced. This callback receives the Austin process and it’s (main) profiled process as instances of psutil.Process, along with the command line of the latter.

Return type

Any

on_terminate(stats)

Terminate event callback.

Implement to be notified when Austin has terminated gracefully. The callback accepts an argument that will receive the global statistics.

Return type

Any

property python_version

The version of the detected Python interpreter.

Return type

Tuple[int, int, int]

abstract start(args=None)

Start Austin.

Every subclass should implement this method and ensure that it spawns a new Austin process.

Return type

Any

submit_sample(data)

Submit a sample to the sample callback.

This method takes care of converting the raw binary data retrieved from Austin into a Python string.

Return type

None

terminate(wait=False)

Terminate Austin.

Stop the underlying Austin process by sending a termination signal.

Return type

None

property version

Austin version.

Return type

Tuple[int, int, int]

All the wrappers documented in this section are subclasses of the austin.BaseAustin class. The purpose is to set a common base API while also providing some convenience methods that you are likely to need, so that you don’t have to implement them yourself.

The start method

The general idea is to subclass austin.BaseAustin and subclass the austin.BaseAustin.start() method with the logic required to start the Austin binary in the background. By default, Austin’s binary is named austin, and you can refer to it with BaseAustin.BINARY. Hence, if you were to start Austin in an asyncio fashion, your start method would be a coroutine starting with:

async def start(self, args: List[str] = []) -> None:
    try:
        self.proc = await asyncio.create_subprocess_exec(
            self.BINARY,
            *(args or sys.argv[1:]),
            stdin=asyncio.subprocess.PIPE,
            stdout=asyncio.subprocess.PIPE,
            stderr=asyncio.subprocess.PIPE,
        )
    except FileNotFoundError:
        raise AustinError("Austin executable not found.")

You should use the optional args argument to pass in the command-line arguments to pass to the Austin binary, as done in the above example.

Note

For the wrappers to work as expected, the Austin binary specified by the BINARY class attribute needs to be on the PATH environment variable or they will fail to start. Of course, this value can be overridden by sub-classes so that this behaviour can be adjusted according to your needs.

The callbacks

The other requirement for making a subclass of austin.BaseAustin concrete is the implementation of the on_sample_received callback. This can either be a class method, or passed via the sample_callback argument to the constructor of the subclass. This callback function must take a single argument of type str, which holds the raw text of a sample collected by Austin.

There are other two recommended callbacks that you might want to implement: austin.BaseAustin.on_ready() and austin.BaseAustin.on_terminate(). See the class documentation below for more details.

The Simple Austin Wrapper

class austin.simple.SimpleAustin(sample_callback=None, ready_callback=None, terminate_callback=None)

Bases: austin.BaseAustin

Simple implementation of Austin.

This is the simplest way to start Austin from Python if you do not need to carry out other operation in parallel. Calling start() returns only once Austin has terminated.

Example:

class EchoSimpleAustin(SimpleAustin):
    def on_ready(self, process, child_process, command_line):
        print(f"Austin PID: {process.pid}")
        print(f"Python PID: {child_process.pid}")
        print(f"Command Line: {command_line}")

    def on_sample_received(self, line):
        print(line)

    def on_terminate(self, data):
        print(data)

try:
    austin = EchoSimpleAustin()
    austin.start(["-i", "10000"], ["python3", "myscript.py"])
except KeyboardInterrupt:
    pass
start(args=None)

Start the Austin process.

Return type

None

The austin.simple.SimpleAustin wrapper is for simple applications that do not require any sort of concurrency or (thread-based) parallelism. For example, your application does not involve a user interface or asynchronous I/O.

The example above shows you how to make a simple echo Austin application that effectively acts like the underlying Austin binary. The on_sample_received is indeed echoing back all the samples that it receives

The asyncio-based Austin Wrapper

class austin.aio.AsyncAustin(sample_callback=None, ready_callback=None, terminate_callback=None)

Bases: austin.BaseAustin

Asynchronous implementation of Austin.

Implements an asyncio API for Austin so that it can be used alongside other asynchronous tasks.

The following example shows how to make a simple asynchronous echo implementation of Austin that behaves exactly just like Austin.

Example:

class EchoAsyncAustin(AsyncAustin):
    def on_ready(self, process, child_process, command_line):
        print(f"Austin PID: {process.pid}")
        print(f"Python PID: {child_process.pid}")
        print(f"Command Line: {command_line}")

    def on_sample_received(self, line):
        print(line)

    def on_terminate(self, data):
        print(data)

if sys.platform == "win32":
    asyncio.set_event_loop(asyncio.ProactorEventLoop())

try:
    austin = EchoAsyncAustin()
    asyncio.get_event_loop().run_until_complete(
        austin.start(["-i", "10000", "python3", "myscript.py"])
    )
except (KeyboardInterrupt, asyncio.CancelledError):
    pass
async start(args=None)

Create the start coroutine.

Use with the asyncio event loop.

Return type

None

This wrapper implements an asyncio-based API around Austin. The start method is, in fact, a coroutine that can be schedule with any asyncio event loops.

The example above shows how to implement the same echo example of the simple case using this wrapper.

The Thread-based Austin Wrapper

class austin.threads.ThreadedAustin(*args, **kwargs)

Bases: austin.simple.SimpleAustin

Thread-based implementation of Austin.

Implements a threading API for Austin so that it can be used alongside other threads.

The following example shows how to make a simple threaded echo implementation of Austin that behaves exactly just like Austin.

Example:

class EchoThreadedAustin(ThreadedAustin):
    def on_ready(self, process, child_process, command_line):
        print(f"Austin PID: {process.pid}")
        print(f"Python PID: {child_process.pid}")
        print(f"Command Line: {command_line}")

    def on_sample_received(self, line):
        print(line)

    def on_terminate(self, data):
        print(data)

try:
    austin = EchoThreadedAustin()
    austin.start(["-i", "10000", "python3", "myscript.py"])
    austin.join()
except KeyboardInterrupt:
    pass
get_thread()

Get the underlying threading.Thread instance.

As this leaks a bit of the implementation, interaction with the returned thread object should be done with care.

Note

This is an extension of the base Austin abstract class.

Return type

Optional[Thread]

join(timeout=None)

Join the thread.

This is the same as calling join() on the underlying thread object.

Note

This is an extension of the base Austin abstract class.

Return type

None

start(args=None)

Start the Austin thread.

Return type

None

This wrapper implements an thread-based API around Austin. This class offers additional methods beside the base API of austin.BaseAustin that allow you to perform operations that are typical of thread-based applications, like joining a thread to ensure a proper termination of the application.

The example above shows how to implement the same echo example of the simple case using this wrapper.

.austinrc

The .austinrc run-control file located in the user’s home folder can be used to configure the wrappers. The basic implementation of austin.config.AustinConfiguration supports the option binary to specify the location of the Austin binary. This is the third lookup option when trying to locate the Austin binary in order to start sampling, as discussed at the top of this page.

class austin.config.AustinConfiguration

Bases: object

Austin configuration borg.

property binary

Get the Austin binary path.

Return type

str

reload()

Reload the configuration from the run-control file.

Return type

None

save()

Save the current configuration to file.

Return type

None

Applications that need custom configuration can sub-class austin.config.AustinConfiguration and modify the internal state self._data, which is then dumped to back to the .austinrc file via a call to save. The file format is TOML.