Python API
Overview
The Python API provides a ctypes-based wrapper around the GCode shared library. It exposes a Pythonic interface with context manager support, exception-based error handling, and dict-like result objects.
from gcode_api import GCode, GCodeError, ErrorCode, ResultType, GCodeResultGetting Started
Prerequisite: Galil GCLIB must be installed on the target machine before using this library. Download it from galil.com.
1. Install
Requires Python 3.10 or later. Install the package with pip:
pip install https://www.galil.com/sw/pub/win/galil_gcode-1.2.1-py3-none-win_amd64.whlTo upgrade to a newer release, run the same command with --upgrade: pip install --upgrade <url>.
Note: the package you install is galil-gcode, but the module you import is gcode_api — i.e. import gcode_api, not import galil_gcode.
2. Verify
Confirm the package is installed and the library loads:
python -c "from gcode_api import GCode; print('OK')"3. Set License Key
GCode() reads your license key from the GCODE_LICENSE_KEY environment variable. Set it once, permanently:
setx GCODE_LICENSE_KEY "your-license-key-here"Important: setx does not update the current terminal session. You must close and reopen your Command Prompt (or PowerShell) before the variable will be visible. Alternatively, pass the key explicitly: GCode("your-license-key-here").
4. Quick Example
Connect to a controller, configure two axes, and execute a move:
from gcode_api import GCode
# License key is read from the GCODE_LICENSE_KEY environment variable
with GCode() as gcode:
gcode.connect("192.168.1.100")
gcode.configure_linear_axis("X", "A", counts_per_unit=1000.0)
gcode.configure_linear_axis("Y", "B", counts_per_unit=1000.0)
gcode.add_command("G1 X10 Y10 F100")
gcode.start()
gcode.wait_for_queue_empty()5. Bundled Examples
The package ships with a tkinter GUI example and a sample G-code file. Run the GUI example directly:
python -m gcode_api.examples.gui_exampleTo find the example source files on disk (for reading or copying):
python -c "from gcode_api import examples; print(examples.__path__[0])"ErrorCode
class ErrorCode(IntEnum)Integer enum of all error codes returned by the underlying C library. When the Python API raises a GCodeError, its error_code attribute is an ErrorCode member.
| Member | Value | Description |
|---|---|---|
OK | 0 | Success |
INVALID_HANDLE | 1 | Handle has been destroyed or is invalid |
NOT_CONNECTED | 2 | Not connected to a controller |
ALREADY_CONNECTED | 3 | Already connected |
CONNECTION_FAILED | 4 | Connection attempt failed |
PARSE_FAILED | 5 | G-code string could not be parsed |
FILE_NOT_FOUND | 6 | File path does not exist |
FILE_READ_ERROR | 7 | File could not be read |
INVALID_ARGUMENT | 8 | Invalid argument provided |
PROCESSING_ACTIVE | 9 | Cannot modify configuration while processing |
TIMEOUT | 11 | Operation timed out |
LICENSE | 12 | License error |
NOT_FOUND | 13 | Key not found in result |
TYPE_MISMATCH | 14 | Result key exists but has a different type |
UNKNOWN | 99 | Unclassified error |
ResultType
class ResultType(IntEnum)Identifies the kind of data carried by a GCodeResult.
| Member | Value | Description |
|---|---|---|
NONE | 0 | No result data |
POSITION | 1 | Axis position data (e.g., from M114) |
MESSAGE | 2 | Text message (e.g., from M118) |
GCodeError
class GCodeError(Exception)Raised when any GCode API call fails. All methods on the GCode class raise this exception instead of returning error codes.
Attributes
error_code—ErrorCodeenum member indicating the failure reasonmessage— Human-readable error description from the C library, or a default derived from the error code name
Example
from gcode_api import GCode, GCodeError, ErrorCode
with GCode("your-license-key-here") as gcode:
try:
gcode.connect("192.168.1.100")
except GCodeError as e:
if e.error_code == ErrorCode.CONNECTION_FAILED:
print(f"Could not reach controller: {e.message}")
else:
raiseGCodeResult
class GCodeResultResult data returned by a command (e.g., position data from M114, a message from M118). Passed to the set_on_command_result callback. The object is safe to store and use after the callback returns.
Properties
| Property | Type | Description |
|---|---|---|
type | ResultType | The kind of result data |
Typed Accessors
| Method | Returns | Description |
|---|---|---|
get_double(key) | Optional[float] | Numeric value or None |
get_int(key) | Optional[int] | Integer value or None |
get_string(key) | Optional[str] | String value or None |
Dict-like Access
GCodeResult also supports standard dict operations for convenience:
result['X'] # KeyError if missing
result.get('X') # None if missing
result.get('X', 0.0) # default if missing
'X' in result # membership test
len(result) # number of fields
dict(result) # convert to plain dictGCode
class GCodeMain entry point for the Python API. Wraps the shared library and manages the underlying handle. Supports context-manager usage for automatic cleanup.
with GCode("your-license-key-here") as gcode:
gcode.connect("192.168.1.100")
# ...Optional: Set GCODE_API_LIB_PATH to override the path to the shared library. This is not required when installed via pip.
Lifecycle
GCode(license_key=None)
gcode = GCode() # reads GCODE_LICENSE_KEY
gcode = GCode("your-license-key-here")Creates a new GCode instance and loads the shared library (on first call). If license_key is omitted, the GCODE_LICENSE_KEY environment variable is used. Raises GCodeError if no license key is available, the library cannot be loaded, the license key is invalid or expired, or the instance cannot be created.
Parameters:
license_key(Optional[str]) — Your license key string (provided by Galil). Defaults to theGCODE_LICENSE_KEYenvironment variable.
close()
gcode.close() -> NoneReleases all resources. Called automatically when exiting a with block. Safe to call multiple times.
Connection Methods
connect()
gcode.connect(ip_address: str) -> NoneConnects to a Galil motion controller at the specified IP address.
Parameters:
ip_address— IP address of the controller (e.g.,"192.168.1.100")
Raises:
GCodeError(ALREADY_CONNECTED)— if already connectedGCodeError(CONNECTION_FAILED)— if connection fails
disconnect()
gcode.disconnect() -> NoneDisconnects from the controller.
is_connected()
gcode.is_connected() -> boolReturns True if connected to a controller, False otherwise.
Command Methods
add_command()
gcode.add_command(gcode_string: str) -> NoneAdds a single G-code command to the execution queue.
Parameters:
gcode_string— G-code command (e.g.,"G1 X10 Y20 F100")
Raises:
GCodeError(PARSE_FAILED)— if the command cannot be parsed
add_file()
gcode.add_file(file_path: str | os.PathLike) -> NoneLoads and queues all G-code commands from a file. Accepts both strings and pathlib.Path objects.
Raises:
GCodeError(FILE_NOT_FOUND)— if the file does not existGCodeError(FILE_READ_ERROR)— if the file cannot be readGCodeError(PARSE_FAILED)— if a command cannot be parsed
get_queue_size()
gcode.get_queue_size() -> intReturns the number of commands currently in the queue.
clear_queue()
gcode.clear_queue() -> NoneRemoves all pending commands from the queue. Does not affect the currently executing command.
Execution Methods
start()
gcode.start() -> NoneStarts or resumes processing the command queue on a background thread. Idempotent: calling when already running is a no-op. If paused (M0/M1 or error), resumes from where it left off.
Raises:
GCodeError(NOT_CONNECTED)— if not connected
stop()
gcode.stop() -> NoneStops processing. The current command completes before stopping. Call start() to resume.
wait_for_queue_empty()
gcode.wait_for_queue_empty(timeout_ms: int = -1) -> NoneBlocks until all queued commands have been processed.
Parameters:
timeout_ms— Maximum wait in milliseconds, or-1for infinite (default)
Raises:
GCodeError(TIMEOUT)— if the timeout expiresGCodeError(NOT_CONNECTED)— if not connected
Configuration Methods
Configuration methods must be called when the processor is not actively running. Calling them during processing raises GCodeError(PROCESSING_ACTIVE).
configure_linear_axis()
gcode.configure_linear_axis(
gcode_axis: str,
dmc_axis: str,
counts_per_unit: float,
forward_limit: float = float("inf"),
) -> NoneMaps a G-code axis letter to a physical DMC controller axis.
Parameters:
gcode_axis— G-code axis letter ("X","Y","Z", etc.)dmc_axis— DMC axis letter ("A"through"H")counts_per_unit— Encoder counts per user unit (e.g., counts per mm)forward_limit— Maximum travel in user units. Defaults to no limit.
Raises:
GCodeError(INVALID_ARGUMENT)— if axis letters are invalidGCodeError(PROCESSING_ACTIVE)— if called while processing
configure_spindle()
gcode.configure_spindle(
dmc_axis: str,
counts_per_revolution: float,
) -> NoneConfigures the DMC axis that controls the spindle.
Parameters:
dmc_axis— DMC axis letter ("A"through"H")counts_per_revolution— Encoder counts per spindle revolution
configure_extruder()
gcode.configure_extruder(
dmc_axis: str,
counts_per_unit: float,
) -> NoneConfigures the DMC axis that controls the extruder.
Parameters:
dmc_axis— DMC axis letter ("A"through"H")counts_per_unit— Encoder counts per user unit
Logging
enable_logging()
gcode.enable_logging(file_path: str | os.PathLike) -> NoneEnables logging to the specified file. Accepts both strings and pathlib.Path objects.
Callbacks
Threading: All callbacks except set_on_started are invoked on a worker thread. Keep callback code simple and thread-safe. Consider using a queue.Queue to pass data to the main thread.
set_on_error()
gcode.set_on_error(
callback: Optional[Callable[[ErrorCode, str, str], None]]
) -> NoneSets a callback for errors during command execution. Pass None to clear.
Callback signature:
def on_error(error_code: ErrorCode, command: str, message: str) -> Noneerror_code—ErrorCodeindicating the failurecommand— The G-code string that caused the errormessage— Human-readable error description
set_on_command_result()
gcode.set_on_command_result(
callback: Optional[Callable[[str, GCodeResult], None]]
) -> NoneSets a callback for when a command produces result data (e.g., M114, M118). Pass None to clear. The GCodeResult object is safe to store and use after the callback returns.
Callback signature:
def on_result(command: str, result: GCodeResult) -> Noneset_on_stopped()
gcode.set_on_stopped(
callback: Optional[Callable[[], None]]
) -> NoneSets a callback for when processing stops (M0/M1 pause, error, or explicit stop() call). Pass None to clear.
set_on_started()
gcode.set_on_started(
callback: Optional[Callable[[], None]]
) -> NoneSets a callback for when processing starts or resumes. Unlike the other callbacks, this one is called on the caller's thread. Pass None to clear.