Skip to content

puthon script #49

@tacomakes

Description

@tacomakes

The script inserts a small Z lift, moves to the target X, then returns Z so the move doesn't drag through the print. Defaults: move to X=0 every 10 layers with a 5 mm lift and a 6000 mm/min travel feed.

#!/usr/bin/env python3
"""
insert_move_every_n_layers.py

Usage (PrusaSlicer post-processing):
prusaslicer will invoke the script; it usually passes input and output filenames.
Example args in PrusaSlicer: --x 0 --every 10 --lift 5 --feed 6000

This script finds lines like ";LAYER:123" and after every Nth layer inserts a short
safe sequence to lift Z, move to X position, then restore Z.

Default values:
x=0.0, every=10, lift=5.0, feed=6000
"""

import sys
import argparse
import re

def parse_args():
p = argparse.ArgumentParser(description="Insert a move to X every N layers in G-code")
p.add_argument("--x", type=float, default=0.0, help="X coordinate to move to (mm)")
p.add_argument("--every", type=int, default=10, help="Do it every N layers (use 1 for every layer)")
p.add_argument("--lift", type=float, default=5.0, help="Relative Z lift before moving (mm)")
p.add_argument("--feed", type=float, default=6000, help="Feedrate for travel move (mm/min)")
p.add_argument("--marker", type=str, default=";MOVE_INSERTED", help="Marker comment to avoid double-insertions")
p.add_argument("infile", nargs="?", default=None, help="Input gcode file (optional, PrusaSlicer usually passes it)")
p.add_argument("outfile", nargs="?", default=None, help="Output gcode file (optional)")
return p.parse_args()

def make_move_block(x, lift, feed, marker):
# Use relative moves for lift and return so we don't need current Z value.
# Sequence:
# ; marker
# G91 ; relative mode
# G1 Z{lift} F3000
# G90 ; absolute mode
# G1 X{x} F{feed}
# G91
# G1 Z-{lift} F3000
# G90
# You may want to tweak feed and retracts for your setup.
lines = [
f"{marker} ; inserted by insert_move_every_n_layers.py",
"G91",
f"G1 Z{lift:.3f} F3000 ; lift before move",
"G90",
f"G1 X{x:.3f} F{feed:.0f} ; travel to X",
"G91",
f"G1 Z-{lift:.3f} F3000 ; lower back down",
"G90",
"" # blank line for readability
]
return "\n".join(lines)

def main():
args = parse_args()

# Input / output file handling
if args.infile and args.outfile:
    infile = args.infile
    outfile = args.outfile
elif args.infile and not args.outfile:
    # If only one file provided, overwrite it safely
    infile = args.infile
    outfile = infile + ".tmp"
else:
    # When PrusaSlicer runs the script it usually supplies input and output file paths.
    # But to be safe, read stdin and write stdout if no files provided.
    infile = None
    outfile = None

content = None
if infile:
    with open(infile, "r", encoding="utf-8") as f:
        content = f.read()
else:
    content = sys.stdin.read()

# Avoid double-inserting by checking for marker presence
if args.marker and args.marker in content:
    # Already ran (or file already contains marker) — do nothing and output original
    out_text = content
else:
    # Process content line by line
    out_lines = []
    layer_re = re.compile(r"^;LAYER:(\s*\d+)", re.IGNORECASE)
    for line in content.splitlines():
        out_lines.append(line)
        m = layer_re.match(line)
        if m:
            try:
                layer_num = int(m.group(1))
            except:
                # fallback: skip if can't parse
                continue
            if args.every > 0 and (layer_num % args.every) == 0:
                # skip inserting at layer 0 (optional) — many people want to skip layer 0
                # If you want to run at layer 0 too, remove the next condition.
                if layer_num == 0:
                    continue
                move_block = make_move_block(args.x, args.lift, args.feed, args.marker)
                out_lines.append(move_block)

    out_text = "\n".join(out_lines) + "\n"

if outfile:
    with open(outfile, "w", encoding="utf-8") as f:
        f.write(out_text)
    # If we created a temp file (infile.tmp), replace original
    if args.infile and not args.outfile:
        import os
        os.replace(outfile, infile)
else:
    sys.stdout.write(out_text)

if name == "main":
main()

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions