Post-processing scripts explained

Hello, I really tried to find some real documentation on this topic, but couldn’t!
Is there some real world mini example how this feature works, what kind of code (python?) one can put into this field and when it is applied and so on?

I just recently began to print with wood PLA and would like to take advantage of eg. these kind of post-processing (GitHub - mbodenham/woodgrain-filament: Program to create woodgrain effect when using wood PLA filament on Creality 3D Ender-3.). Would that be possible using this Bambu Studio input field?

I am also interested to learn more about this and will be following the thread.

In the meantime, there are some other ways to achieve woodgrain effects available/explained on MakerWorld.
Here are two very different approaches:
Add Wood Grain Effects to Your Models - Using a Small Plate as an Example by PandaN MakerWorld: Download Free 3D Models
How to print Wood by NPeter MakerWorld: Download Free 3D Models

1 Like

I looked at this feature three years ago when I first got into the Bambu ecosystem. I checked again and it doesn’t look like this topic has advanced at all either in the Orca GitHub community or elsewhere.

Here’s what my research points to:

  1. This appears to be vestigial Slic3r-era functionality inherited by modern slicers such as PrusaSlicer and Cura.

  2. Everything suggests it only runs when the file is sliced. The slicer calls an external routine with the G-Code filename as an argument. Here’s how I tested it. It executed the BAT file at the click of the slice plate action but I couldn’t backtrack what happened after that. I couldn’t find the file it operated on. It’s probably staring me in the face but I couldn’t find it.

If you’re looking for documentation. The closest I came to was this old manual. It is very sparse but gives Slic3r examples.

https://manual.slic3r.org/advanced/post-processing

3 Likes

Sorry, I mixed two questions here. The question about the post-processing script and my motivation for it, the wood look.

Thanks for the links to the approaches for wood imitation. The second link changes the 3D shape and creates spatial contours, while the first link seems to be more like the approach described at gcode_postprocessors/wood/Woodgrain_Cura.py at master · MoonCactus/gcode_postprocessors · GitHub, where different nozzle temperature leads to different colors of the wood PLA. Thanks for the links. I need to look into the topic in more detail.

1 Like

That’s very interesting. I hadn’t realized that BambuStudio (Software Bambu Studio | Bambu Lab US) is based on open source software and is itself open source (GitHub - bambulab/BambuStudio: PC Software for BambuLab and other 3D printers).

I’ll definitely give it a try now that you’ve shared links to sample scripts. Let’s see how and if it works. It looks like the script simply gets the GCODE on stdin and returns the modified GCODE on stdout. Something like that, right?

I believe that is correct. The paramters that I saw posted elsewhere - can’t find the link at the moment - looked something like this ( this is from memory so don’t hold me to it):

"C:\Path\To\Python\python.exe" "C:\Path\To\myscript.py" "{input_file}" "{output_file}"

What I was never able to prove is that there was in fact an output file that was sent to the printer. But in all candor, I didn’t test it that far. I guess one simple test would be to create a simple primitive like a cube, save that to a G-Coded file on the local system. Then generate a cylinder primitive, slice it, then create a simple script which calls that file as the output. If one gets the cylinder, then one knows it didn’t work, if a cube is output, then there is the proof. I may try this at some point.

2 Likes

So with your help and the links to Slic3r I was able to come up with some basic shell script as a test case.

#!/bin/sh
echo "file: $*" > /Users/matths/pps/output.log
env | grep ^SLIC3R >> /Users/matths/pps/output.log
cp $* /Users/matths/pps/gcode2.txt # save sphere gcode
cp /Users/matths/pps/gcode.txt $* # replace with cube gcode

I loaded a sphere object, added the path to this script in post-processing scripts field.

Then I did hit the slice button. The preview then still shows a slices sphere, but when I download the result using the ‘export sliced file’ button, it was the cube gcode and not the sphere. So my script did work. I did not send it to the printer yet.

So a script just needs to overwrite the file. Sounds easy. I’ll check tomorrow with printing.

I was also able to log a lot of SLIC3R prefixed environment variables from within the script that might be useful, maybe.

3 Likes

Thanks for sharing this data. It is very helpful. Let us know how the print turns out and anything you may learn. This really helps the community.

It may also help my motivation to try out some calibration ideas I’ve had for a while but really have been just too lazy to fight HAL. :yum:

2 Likes

I’ve tried post-processing scripts to disable bed heating 5 minutes before print ends, so that i could grab part instantly after printing. Gemini was very helpful at explaining and writing script.

If you are interested, here’s how I did it:

  1. install python from official python website (or microsoft store on Windows).
  2. When it asks while installing:
We can add the directory (C:\Users\YourName\AppData\Local\Python\bin) to PATH now,

but you will need to restart your terminal to use it. The entry will be removed

if you run py uninstall --purge, or else you can remove it manually when

uninstalling Python.

Add commands directory to your PATH now? [y/N]

write ‘y’ and press enter. Then I restarted PC, not sure if i had to.

  1. open cmd in windows and write “where python”. This will be first filepath you will need for bambu studio eg. “C:\Users\YourName\AppData\Local\Python\bin\python.exe”.

  2. create your script file wherever you want and save it with .py extension. Absolute path to this file will be second filepath you will need for bambustudio eg. “C:\Users\YourName\Documents\myScript.py”.

  3. Now you need to enter into bambu studio Process / others / Post-processing script and copy both paths with semicolons and space between them like this:
    "C:\Users\YourName\AppData\Local\Python\bin\python.exe" "C:\Users\YourName\Documents\myScript.py";

Now this script should run on every slicing, remember to put something in myScript.py file :slight_smile:

My script for turning off bed 5 minutes before end looks like this (open myScript.py with notepad or any differect text-editor and put it inside):

import sys
import re
import os
import datetime

# --- CONFIGURATION ---
MINUTES_BEFORE_END = 5
MIN_PROGRESS_PERCENT = 10  # % - prevents turning off the bed at startup/calibration
# ---------------------

def log_debug(message):
    # Saves logs to 'debug_log.txt' in the same folder as this script
    log_path = os.path.join(os.path.dirname(sys.argv[0]), "debug_log.txt")
    with open(log_path, "a") as log:
        log.write(f"[{datetime.datetime.now()}] {message}\n")

try:
    # Check if the Slicer provided the G-code file path
    if len(sys.argv) < 2:
        sys.exit(1)

    source_file = sys.argv[1]
    
    with open(source_file, "r") as f:
        lines = f.readlines()

    output_lines = []
    bed_turned_off = False
    
    # Regex to find: M73 P(progress) R(minutes_remaining)
    # Example: M73 P15 R4 (15% progress, 4 minutes left)
    pattern = re.compile(r"M73 P(\d+) R(\d+)")

    for line in lines:
        if not bed_turned_off:
            match = pattern.search(line)
            if match:
                progress = int(match.group(1))
                minutes_left = int(match.group(2))
                
                # CONDITION: Less than X minutes left AND progress > Y% (to ignore header/start)
                if minutes_left <= MINUTES_BEFORE_END and progress > MIN_PROGRESS_PERCENT:
                    log_debug(f"Trigger found: {minutes_left} min remaining at {progress}% progress.")
                    
                    output_lines.append(f"; --- AUTO COOL DOWN (script: {minutes_left} min left / {progress}% done) ---\n")
                    output_lines.append("M140 S0 ; Turn off bed heating\n")
                    output_lines.append("; -------------------------------\n")
                    
                    bed_turned_off = True
        
        output_lines.append(line)

    # Overwrite the original G-code file
    with open(source_file, "w") as f:
        f.writelines(output_lines)

except Exception as e:
    log_debug(f"CRITICAL ERROR: {str(e)}")
    sys.exit(1)

When succesful, new file “debug_log.txt” should be created in your script directory after slicing, you can see inside if there was any error.

2 Likes