Home > database >  Insert Item into line on text file with Python
Insert Item into line on text file with Python

Time:08-11

I have a large gcode/text file. I want to search the file and if a line contains the word 'layer' like:

; layer 1, Z = 0.500

Then I want to add this below it once every x amount of layers:

;Clean Nozzle
G0 X30 Y-47 F10000
G0 X70 Y-47
G0 X30 Y-47

This will tell the nozzle of a 3D printer to pass over a fixed wire brush to clean the nozzle. I don't want it to do this every layer, just once every X amount of layers.

My Python Script so far looks very confusing and doesn't work, so I think I should re-start from scratch. My plan was:

  • To use the variable 'LayerCount' to count how many new layers had passed and eventually add something to say every 10 layers add the cleaning thing in.
  • To use the Variable 'index' to get it to insert the lines between the right lines of code.
  • It is using mmap because I saw that its better for handling large text files, for example I have one here that is 78MB.

Code so far:

#!/usr/bin/env python3
import mmap

LayerCount = 1                                                           #Start layer counter at 1,  this will get increased every time a line includes the word 'layer' (later in this script)
index = 0
#open gcode file
with open('C:\\Users\\Adam.Widdowson\\Desktop\\gcode\\TestSmall.gcode', 'rb', 0) as file, \
    mmap.mmap(file.fileno(), 0, access=mmap.ACCESS_READ) as s:      #weird mmap stuff is aparently better for large files
    contents = file.readlines()                                     #Makes a list called 'contents' containing each value in the gcode
    print('List:')
    print(contents)                                                 #Prints to terminal for sense checking

    #Create new gcode file containing the info.
    with open(r'C:\\Users\\Adam.Widdowson\\Desktop\\gcode\\New.gcode', 'w') as fp:
        for item in contents:                                       #I think this takes each item in the list 'contents' and makes 'item' = it
            itemSTR=str(item, 'utf-8')                              #Convert item into a utf-8 string
            print('----------------------------------------')
            print('index of item:')
            print(index)
            print('Item in list:')
            print(itemSTR)
            print('Layer:')
            print(LayerCount)
            index = index   1
            if 'layer' in itemSTR:
                print('Layer Change')
                contents.insert(index,'Clean Nozzle')
                LayerCount = LayerCount   1
            fp.write("%s\n" % item) # write each item on a new line



print('done')               #Prints done to terminalDone'

Thanks

CodePudding user response:

I used the reply from @philosofool and made a couple of edits and this now works for me.

Notes:

  • Index is set to -1 as the software that generates the gcode adds the word 'layer' in the comments twice before the main script starts.
  • I removed 'rb' from this line so the file opens in plain text:
with open(path, 'rb') as file:
  • I have also changed:
if line.contains('layer'):

to this as it didn't seem to like it:

if 'layer' in line:
  • Finally I further indented the modulus code that adds the cleaning script, so that it only adds the clean nozzle script if the line contains the word layer. Otherwise it was adding it to all lines that occur before the first line containing 'layer' as the index was '0' and 0/10 has no remainder.

Full Code:


###SETUP:
index = -1
acc_lines = ''  # short for accumulated lines.
frequency = 10
path = 'C:\\Users\\Adam.Widdowson\\Desktop\\gcode\\TestSmall.gcode'
new_path = r'C:\\Users\\Adam.Widdowson\\Desktop\\gcode\\New.gcode'

# use triple " for handy preformatted text.
clean_cmd = """; Clean Nozzle
G0 X30 Y-47 F10000
G0 X70 Y-47
G0 X30 Y-47
"""


###OPEN GCODE FILE:
with open(path) as file:
    for line in file.readlines():
        acc_lines = acc_lines   line
        if 'layer' in line:
            index  = 1
            if index % frequency == 0:
                acc_lines = acc_lines   clean_cmd

###WRITE NEW FILE:
with open(new_path, 'w') as file:
    file.write(acc_lines)

CodePudding user response:

I think you should be okay reading a 78MB file. I don't usually think about "good for handling large" until I'm sure I'm going over 2GB. (I'm a data scientist and over 2GB is a daily thing for me.) My suggestion would be to use the modulus operator, %, to determine whether to insert text. Modulus returns the remainder of division, so if x % 10 == 0 is true, you are on an iteration divisible by ten.


# LayerCount = 1                                                           
index = 0
acc_lines = ''  # short for accumulated lines.
frequency = 10
path = 'C:\\Users\\Adam.Widdowson\\Desktop\\gcode\\TestSmall.gcode'
new_path = r'C:\\Users\\Adam.Widdowson\\Desktop\\gcode\\New.gcode'

# use triple " for handy preformatted text.
clean_cmd = """ ;Clean Nozzle
G0 X30 Y-47 F10000
G0 X70 Y-47
G0 X30 Y-47
"""


#open gcode file
with open(path, 'rb') as file:
    for line in file.readlines():
        acc_lines = acc_lines   line
        if line.contains('layer'):
            index  = 1
            if index % frequency == 0:
                acc_lines = acc_lines   clean_cmd

# you are reading bytes but writing plain text in your code above.
# Not sure why that is. No cause for alarm, but it something is amiss
# when reading the new_path file later, check on this. 

with open(new_path, 'w') as file:
    file.write(acc_lines)
  • Related