Create a simple Python remap
Use a Python remap when the code needs interpreter state or logic that would be awkward in an NGC procedure. This example defines M401, requires a P word, and accepts an optional Q word. It reports the supplied values and finishes immediately.
The example machine directory is /data/ctrl/configs/my-machine.
Configure Python loading
Section titled “Configure Python loading”Create toplevel.py beside the machine’s INI file:
import remapThen add the module path, top-level file, and remap definition to the INI file:
[RS274NGC]REMAP = M401 modalgroup=10 argspec=Pq python=m401
[PYTHON]TOPLEVEL = toplevel.pyPATH_PREPEND = /data/ctrl/configs/my-machineImporting remap makes the functions in remap.py available to the interpreter.
Write the remap function
Section titled “Write the remap function”Create remap.py beside toplevel.py:
from emccanon import MESSAGEfrom interpreter import INTERP_OK
def m401(self, **words): if not self.task: return INTERP_OK
message = "M401 received P=%.6f" % words["p"] if "q" in words: message += " Q=%.6f" % words["q"] MESSAGE(message) return INTERP_OKargspec=Pq validates the block before calling the function. The required P and any supplied Q arrive in words under lowercase keys.
LinuxCNC calls the function while generating the program preview as well as while actually running the program. During preview, self.task is false. Put this check at the start of a remap that produces messages or causes other side effects so preview can inspect the program without performing the action.
Returning INTERP_OK completes the remapped code and lets the interpreter continue.
Restart LinuxCNC, then try these commands in MDI:
| Command | Result |
|---|---|
M401 |
Interpreter error because the required P word is missing. |
M401 P25 |
Operator message: M401 received P=25.000000. |
M401 P25 Q2 |
Operator message: M401 received P=25.000000 Q=2.000000. |

When queued work must finish first
Section titled “When queued work must finish first”LinuxCNC normally reads ahead: the interpreter can prepare later blocks while earlier motion and machine commands are still queued. Most remaps should leave that behavior alone.
Some remaps need the result of queued work before Python can make its next decision. Probing is the familiar example: the probe move must finish before its measured position is meaningful. Tool changes and input waits have the same requirement. These operations are called queue busters because they stop read-ahead at that point.
A Python remap can wait at the same boundary by yielding INTERP_EXECUTE_FINISH:
from emccanon import GET_EXTERNAL_DIGITAL_INPUT, MESSAGE, WAITfrom interpreter import INTERP_EXECUTE_FINISH
def m402(self, **words): if not self.task: return
# Input 0, digital input, wait until high, 5 s timeout. WAIT(0, 1, 3, 5.0) yield INTERP_EXECUTE_FINISH
# The input value is current after LinuxCNC resumes the function. if GET_EXTERNAL_DIGITAL_INPUT(0, 0): MESSAGE("M402 input is high") else: MESSAGE("M402 input wait timed out")The four WAIT arguments select input 0, a digital input (1), wait-until-high mode (3), and a five-second timeout. The yield does not run work in the background. It tells LinuxCNC to execute everything queued so far, synchronize the interpreter with the resulting machine state, and then resume the function after the yield.
Because a function containing yield is a generator, finish it with return or by reaching the end; do not return INTERP_OK from it. Do not call self.execute() after the yield. For a long-running machine action, use Remap a machine action: Ctrl’s executor helper already yields at each poll, so the remap does not implement queue busting itself.