A simple boilerplate Python app for Assetto Corsa that demonstrates UI creation, event handling, configuration management and telemetry data access.
- Speed: Current speed with toggle between KPH/MPH
- Gear: Current gear (R, N, 1, 2, 3, etc.)
- Lap Count: Number of completed laps
- Fuel: Current fuel level in liters
-
Copy the entire
ac-python-app-examplefolder to your Assetto Corsa installation:<AC Installation>/apps/python/ac-python-app-example/
Typical AC installation path:
- Windows:
C:\Program Files (x86)\Steam\steamapps\common\assettocorsa\apps\python\ac-python-app-example\
- Windows:
-
Launch Assetto Corsa and start a session
-
Open the app sidebar (in-game) and activate "ac-python-app-example"
If you're actively developing the app:
-
Create a symbolic link from your development folder to the AC apps directory:
mklink /D "C:\...\assettocorsa\apps\python\ac-python-app-example.py" "e:\Dokumente2\Programmierung\ac-python-app-example\ac-python-app-example.py"
-
Edit files in your development folder and reload in AC
ac-python-app-example/
├── ac-python-app-example.py # Main application file
├── settings.ini # User configuration (editable)
├── settings_defaults.ini # Default configuration (reference)
├── lib/
│ └── sim_info.py # Shared memory interface
├── stdlib/
│ ├── _ctypes.pyd # 32-bit DLL (must be copied)
│ └── README.txt # Instructions
└── stdlib64/
├── _ctypes.pyd # 64-bit DLL (must be copied)
└── README.txt # InstructionsEdit settings.ini to customize the app:
[Display]
speed_unit = kph # or "mph"
show_extra_info = 1 # 0 to hide, 1 to show
[Updates]
high_frequency = 0.0167 # Update interval for speed/gear (~60 FPS)
medium_frequency = 0.5 # Update interval for lap/fuel (2 Hz)The app follows the standard AC Python app structure:
-
acMain(ac_version): Called once when the app initializes- Creates the app window
- Sets up all UI elements (labels, buttons)
- Loads configuration
- Returns the app name
-
acUpdate(deltaT): Called every frame- Updates telemetry data
- Uses timers to control update frequency
- Handles both high-frequency (speed, gear) and lower-frequency (lap, fuel) updates
-
acShutdown(): Called when the session ends- Saves configuration
- Performs cleanup
# Define at module level
label_speed = None
def acMain(ac_version):
global label_speed # Declare as global
label_speed = ac.addLabel(appWindow, "Speed: 0")def on_button_toggle(*args):
# Handle button click
global speed_unit
speed_unit = "mph" if speed_unit == "kph" else "kph"
# In acMain:
button = ac.addButton(appWindow, "Toggle")
ac.addOnClickedListener(button, on_button_toggle)timer_high = 0.0
def acUpdate(deltaT):
global timer_high
timer_high += deltaT
if timer_high >= 0.0167: # ~60 FPS
timer_high = 0.0
# Update speed, gear, etc.AC API (basic telemetry):
speed = ac.getCarState(0, acsys.CS.SpeedKMH)
laps = ac.getCarState(0, acsys.CS.LapCount)Shared Memory (advanced data):
from lib.sim_info import info
fuel = info.physics.fuel
gear = info.physics.gear
rpm = info.physics.rpms# 1. Add global variable
label_new = None
# 2. Create in acMain
def acMain(ac_version):
global label_new
label_new = ac.addLabel(appWindow, "Text")
ac.setPosition(label_new, x, y)
ac.setFontSize(label_new, size)
# 3. Update in acUpdate
def acUpdate(deltaT):
global label_new
value = ac.getCarState(0, acsys.CS.SomeValue)
ac.setText(label_new, "New: {}".format(value))# 1. Define handler
def on_new_button_click(*args):
ac.console("Button clicked!")
# 2. Create in acMain
button_new = ac.addButton(appWindow, "Click Me")
ac.setPosition(button_new, x, y)
ac.setSize(button_new, width, height)
ac.addOnClickedListener(button_new, on_new_button_click)# 1. Add to settings.ini
[MySection]
my_option = value
# 2. Load in load_config()
if config.has_section('MySection'):
my_option = config.get('MySection', 'my_option')
# 3. Save in save_config()
config.set('MySection', 'my_option', str(my_option))acsys.CS.SpeedKMH- Speed in km/hacsys.CS.LapCount- Completed lapsacsys.CS.LapTime- Current lap time (ms)acsys.CS.LastLap- Last lap time (ms)acsys.CS.BestLap- Best lap time (ms)- Many more (see AC Python documentation)
info.physics.fuel- Current fuelinfo.physics.gear- Current gearinfo.physics.rpms- Engine RPMinfo.physics.speedKmh- Speedinfo.physics.tyreCoreTemperature- Tire temps (array)info.physics.abs- ABS levelinfo.physics.tc- TC levelinfo.graphics.completedLaps- Laps completedinfo.graphics.position- Race positioninfo.static.maxRpm- Max RPMinfo.static.maxFuel- Max fuel capacity- Many more (see
lib/sim_info.pyfor complete structure)
Press Home key in-game to open the console. Messages sent via ac.console() appear here.
Located in <Documents>\Assetto Corsa\logs\:
py_log.txt- Python app messages (fromac.log())log.txt- AC system logs (includes error messages with line numbers)
App doesn't appear in sidebar:
- Check
log.txtfor error messages - Ensure folder name matches:
boilerplate/boilerplate.py - Verify
_ctypes.pydfiles are copied correctly
Import errors:
acandacsysimports will show errors in IDE - this is normal- These modules only exist within AC's Python environment
Shared memory errors:
- Ensure
_ctypes.pydfiles are in correctstdlib/stdlib64folders - Check that
lib/sim_info.pyexists
- Edit code in your editor
- Start a session in AC (no need to restart AC completely)
- Check console (Home key) for immediate errors
- Test functionality
- End session and repeat
Tip: Use Practice mode on a short track (like Silverstone International) for faster testing.
- AC App Development Tutorial - A GitHub tutorial on creating AC Python apps
MIT License - Feel free to use this as a starting point for your own apps!
Inspired by:
- LmpGUI app structure
- AC community tutorials and shared memory implementations