I am working on a project where I have to edit offsets manually in CNC programs. I would like to do this in python, however, my experience with it has not involved something like this. Any help is greatly appreciated.
example of code:
N0880M41
N0890G50S3600
M03
N0900G96S0210M03
N0910Z23.274M08
N0920M07
N0930Z23.2063
N0940X1.39
N0950G99
N0960G01X1.29F.009
N0970X1.2558
N0980G02X1.189Z23.1662R.944
N0990G01Z14.7569F.012
N1000G02X1.2558Z14.7168R.944
N1010G01X1.29
N1020G00X1.3608Z14.7522
N1030Z23.1309
N1040X1.2656
N1050G01X1.189Z23.1662F.009
N1060G02X1.088Z23.0955R.944
N1070G01Z14.8276F.012
N1080G02X1.2528Z14.7185R.944
N1090G00X1.3236Z14.7538
N1100Z23.0602
N1110X1.1646
N1120G01X1.088Z23.0955F.009
N1130G02X.987Z23.0075R.944
N1140G01Z14.9157F.012
N1150G02X1.1446Z14.7864R.944
N1160G00X1.2152Z14.8217
N1170Z22.9721
N1180X1.0636
N1190G01X.987Z23.0075F.009
N1200G02X.886Z22.8873R.944
N1210G01Z15.0359F.012
N1220G02X1.0344Z14.8716R.944
N1230G00X1.105Z14.907
N1240Z22.8519
I need to change the Z value with a user input via prompt and I wanted to have it output with the same text as the input just with a new value in Z
for example: user prompted and entered value .226
input = N0910Z23.274M08
I would like output to be
output = N0910Z23.500M08
Here is a quick and dirty program that does what you want:
# GCode utility - adjust Z offset
# This code assumes Python 3
import re
def get_float(prompt):
while True:
try:
return float(input(prompt))
except ValueError:
pass
# Regular expression to recognize a Z parameter
z_re = re.compile("Z(-?\d+(?:\.\d*)?)", re.I)
# Create callback function for re.sub
def make_z_callback(dz, fmt="Z{:0.4f}"):
def z_callback(match):
z_value = match.group(1) # get just the number
z_value = float(z_value) + dz # add offset
return fmt.format(z_value) # convert back to string
return z_callback
def main():
# read GCode file contents
fname = input("Enter GCode file name: ")
with open(fname) as inf:
gcode = inf.read()
# do search-and-replace on Z parameters
z_offset = get_float("Enter Z offset: ")
z_callback = make_z_callback(z_offset)
gcode = z_re.sub(z_callback, gcode)
# write result back to file
with open(fname, "w") as outf:
outf.write(gcode)
if __name__=="__main__":
main()
Related
As the title side, I am trying to create small programs to do simple calculations on data read in from text files. But I don't know how to turn the elements from the text file into integers. Any help would be greatly appreciated.
enter code heredef main():
f = input('enter the file name')
# this line open the file and reads the content f + '.txt' is required
getinfo = open(f +'.txt','r')
content = getinfo.read()
num = []
print('here are the number in your file', num)
getinfo.close()
main ()
If your .txt file is in this format,
1
2
3
4
Then you can use the split function on content like this:
f = input('enter the file name')
# this line open the file and reads the content f + '.txt' is required
getinfo = open(f +'.txt','r')
content = getinfo.read()
num = content.split("\n") # Splits the content by every new line
print('here are the number in your file', num)
getinfo.close()
If you need everything in num to be of type int then you can do a for loop to do that like this
f = input('enter the file name')
# this line open the file and reads the content f + '.txt' is required
getinfo = open(f +'.txt','r')
content = getinfo.read()
num = content.split("\n") # Splits the content by every new line
for i in range(len(num)):
num[i] = int(num[i])
print('here are the number in your file', num)
getinfo.close()
One thing you need to be careful of, however, is to make sure that your text file doesn't contain any characters instead of numbers, otherwise python will try to convert something like "c" to an integer which will cause an error.
Other questions don't seem to be getting answered or are not getting answered for Python. I'm trying to get it to find the keyword "name", set the position to there, then set a variable to that specific line, and then have it use only that piece of text as a variable. In shorter terms, I'm trying to locate a variable in the .txt file based on "name" or "HP" which will always be there.
I hope that makes sense...
I've tried to use different variables like currentplace instead of namePlace but neither works.
import os
def savetest():
save = open("nametest_text.txt", "r")
print("Do you have a save?")
conf = input(": ")
if conf == "y" or conf == "Y" or conf == "Yes" or conf == "yes":
text = save.read()
namePlace = text.find("name")
currentText = namePlace + 7
save.seek(namePlace)
nameLine = save.readline()
username = nameLine[currentText:len(nameLine)]
print(username)
hpPlace = text.find("HP")
currentText = hpPlace + 5
save.seek(hpPlace)
hpLine = save.readline()
playerHP = hpLine[currentText:len(hpLine)]
print(playerHP)
os.system("pause")
save.close()
savetest()
My text file is simply:
name = Wubzy
HP = 100
I want it to print out whatever is put after the equals sign at name and the same for HP, but not name and HP itself.
So it should just print
Wubzy
100
Press any key to continue . . .
But it instead prints
Wubzy
Press any key to continue . . .
This looks like a good job for a regex. Regexes can match and capture patterns in text, which seems to be exactly what you are trying to do.
For example, the regex ^name\s*=\s*(\w+)$ will match lines that have the exact text "name", followed by 0 or more whitespace characters, an '=', and then another 0 or more whitespace characters then a one or more letters. It will capture the word group at the end.
The regex ^HP\s*=\s*(\d+)$ will match lines that have the exact text "HP", followed by 0 or more whitespace characters, an '=', and then another 0 or more whitespace characters then one or more digits. It will capture the number group at the end.
# This is the regex library
import re
# This might be easier to use if you're getting more information in the future.
reg_dict = {
"name": re.compile(r"^name\s*=\s*(\w+)$"),
"HP": re.compile(r"^HP\s*=\s*(\d+)$")
}
def savetest():
save = open("nametest_text.txt", "r")
print("Do you have a save?")
conf = input(": ")
# instead of checking each one individually, you can check if conf is
# within a much smaller set of valid answers
if conf.lower() in ["y", "yes"]:
text = save.read()
# Find the name
match = reg_dict["name"].search(text)
# .search will return the first match of the text, or if there are
# no occurrences, None
if(match):
# With match groups, group(0) is the entire match, group(1) is
# What was captured in the first set of parenthesis
username = match.group(1)
else:
print("The text file does not contain a username.")
return
print(username)
# Find the HP
match = reg_dict["HP"].search(text)
if(match):
player_hp = match.group(1)
else:
print("The text file does not contain a HP.")
return
print(player_hp)
# Using system calls to pause output is not a great idea for a
# variety of reasons, such as cross OS compatibility
# Instead of os.system("pause") try
input("Press enter to continue...")
save.close()
savetest()
Use a regex to extract based on a pattern:
'(?:name|HP) = (.*)'
This captures anything that follows an equal to sign preceded by either name or HP.
Code:
import re
with open("nametest_text.txt", "r") as f:
for line in f:
m = re.search(r'(?:name|HP) = (.*)', line.strip())
if m:
print(m.group(1))
Simplest way may be to use str.split() and then print everything after the '=' character:
with open("nametest_text.txt", "r") as f:
for line in f:
if line.strip():
print(line.strip().split(' = ')[1])
output:
Wubzy
100
Instead of trying to create and parse a proprietary format (you will most likely hit limitations at some point and will need to change your logic and/or file format), better stick to a well-known and well-defined file format that comes with the required writers and parsers, like yaml, json, cfg, xml, and many more.
This saves a lot of pain; consider the following quick example of a class that holds a state and that can be serialized to a key-value-mapped file format (I'm using yaml here, but you can easily exchange it for json, or others):
#!/usr/bin/python
import os
import yaml
class GameState:
def __init__(self, name, **kwargs):
self.name = name
self.health = 100
self.__dict__.update(kwargs)
#staticmethod
def from_savegame(path):
with open(path, 'r') as savegame:
args = yaml.safe_load(savegame)
return GameState(**args)
def save(self, path, overwrite=False):
if os.path.exists(path) and os.path.isfile(path) and not overwrite:
raise IOError('Savegame exists; refusing to overwrite.')
with open(path, 'w') as savegame:
savegame.write(yaml.dump(self.__dict__))
def __str__(self):
return (
'GameState(\n{}\n)'
.format(
'\n'.join([
' {}: {}'.format(k, v)
for k, v in self.__dict__.iteritems()
]))
)
Using this simple class exemplarily:
SAVEGAMEFILE = 'savegame_01.yml'
new_gs = GameState(name='jbndlr')
print(new_gs)
new_gs.health = 98
print(new_gs)
new_gs.save(SAVEGAMEFILE, overwrite=True)
old_gs = GameState.from_savegame(SAVEGAMEFILE)
print(old_gs)
... yields:
GameState(
health: 100
name: jbndlr
)
GameState(
health: 98
name: jbndlr
)
GameState(
health: 98
name: jbndlr
)
Made a program that allows the user to enter some text and have a text file be created with that text inside it. However, when the user puts \n it doesn't start a new line. Finding it very difficult to use my program to create text files as it writes all the text on one line lol
Thanks
EDIT - Sorry. Here is my code (Just the part we are concerned with).
class ReadWriteEdit:
def Read(File):
ReadFile = open(File,"r").read()
print(ReadFile)
def Write(File, Text):
WriteFile = open(File,"w")
WriteFile.write(Text)
def Edit(File, Text):
EditFile = open(File,"a")
EditFile.write(Text)
def Write():
print("WRITE")
print("Enter a file location / name")
FileInput = input("-:")
print("Enter some text")
TextInput = input("-:")
ReadWriteEdit.Write(FileInput, TextInput)
As you have found, special escaped characters are not interpolated in strings read from input, because normally we want to preserve characters, not give them special meanings.
You need to do some adjustment after the input, for example:
>>> s=input()
hello\nworld
>>> s
'hello\\nworld'
>>> s = s.replace('\\n', '\n')
>>> s
'hello\nworld'
>>> print(s)
hello
world
You can just add your input to the variable. You didn't provide any code so I'll just have to improvise:
data = open('output.txt', 'w')
a = input('>>')
data.write(a + '\n')
data.close()
But the better solution would be, like the comment below me mentioned, to use sys.stdin.readline()
import sys
data.write(sys.stdin.readline())
The easiest (dirtiest?) way IMHO is to print the message and then use input() without a prompt (or with the last part of it)
print("Are we REALLY sure?\n")
answer = input("[Y/n]")
Write a program that inputs a JSON file (format just like
example1.json) and prints out the value of the title field.
import json
# TODO: Read your json file here and return the contents
def read_json(filename):
dt = {}
# read the file and store the contents in the variable 'dt'
with open(filename,"r") as fh:
dt = json.load(fh)
###fh = open(filename, "r")
###dt = json.load(fh)
return dt
# TODO: Pass the json file here and print the value of title field. Remove the `pass` statement
def print_title(dt):
print filename["title"]
# TODO: Input a file from the user
filename = raw_input("Enter the JSON file: ")
# The function calls are already done for you
r = read_json(filename)
print_title(r)
Hi, I'm new with Python and I'm not sure what I am doing wrong. I keep getting the following message:
enter image description here
Your'e almost there, you just confused with the parameter name.
Change this:
def print_title(dt):
print filename["title"]
To:
def print_title(dt):
print dt["title"]
Below is a script to read velocity values from molecular dynamics trajectory data. I have many trajectory files with the name pattern as below:
waters1445-MD001-run0100.traj
waters1445-MD001-run0200.traj
waters1445-MD001-run0300.traj
waters1445-MD001-run0400.traj
waters1445-MD001-run0500.traj
waters1445-MD001-run0600.traj
waters1445-MD001-run0700.traj
waters1445-MD001-run0800.traj
waters1445-MD001-run0900.traj
waters1445-MD001-run1000.traj
waters1445-MD002-run0100.traj
waters1445-MD002-run0200.traj
waters1445-MD002-run0300.traj
waters1445-MD002-run0400.traj
waters1445-MD002-run0500.traj
waters1445-MD002-run0600.traj
waters1445-MD002-run0700.traj
waters1445-MD002-run0800.traj
waters1445-MD002-run0900.traj
waters1445-MD002-run1000.traj
Each file has 200 frames of data to analyse. So I planned in such a way where this code is supposed to read in each traj file (shown above) one after another, and extract the velocity values and write in a specific file (text_file = open("Output.traj.dat", "a") corresponding to the respective input trajectory file.
So I defined a function called 'loops(mmm)', where 'mmm' is a trajectory file name parser to the function 'loops'.
#!/usr/bin/env python
'''
always put #!/usr/bin/env python at the shebang
'''
#from __future__ import print_function
from Scientific.IO.NetCDF import NetCDFFile as Dataset
import itertools as itx
import sys
#####################
def loops(mmm):
inputfile = mmm
for FRAMES in range(0,200):
frame = FRAMES
text_file = open("Output.mmm.dat", "a")
def grouper(n, iterable, fillvalue=None):
args = [iter(iterable)] * n
return itx.izip_longest(fillvalue=fillvalue, *args)
formatxyz = "%12.7f%12.7f%12.7f%12.7f%12.7f%12.7f"
formatxyz_size = 6
formatxyzshort = "%12.7f%12.7f%12.7f"
formatxyzshort_size = 3
#ncfile = Dataset(inputfile, 'r')
ncfile = Dataset(ppp, 'r')
variableNames = ncfile.variables.keys()
#print variableNames
shape = ncfile.variables['coordinates'].shape
'''
do the header
'''
print 'title ' + str(frame)
text_file.write('title ' + str(frame) + '\n')
print "%5i%15.7e" % (shape[1],ncfile.variables['time'][frame])
text_file.write("%5i%15.7e" % (shape[1],ncfile.variables['time']\
[frame]) + '\n')
'''
do the velocities
'''
try:
xyz = ncfile.variables['velocities'][frame]
temp = grouper(2, xyz, "")
for i in temp:
z = tuple(itx.chain(*i))
if (len(z) == formatxyz_size):
print formatxyz % z
text_file.write(formatxyz % z + '\n')
elif (len(z) == formatxyzshort_size):
print formatxyzshort % z
text_file.write(formatxyzshort % z + '\n' )
except(KeyError):
xyz = [0] * shape[2]
xyz = [xyz] * shape[1]
temp = grouper(2, xyz, "")
for i in temp:
z = tuple(itx.chain(*i))
if (len(z) == formatxyz_size):
print formatxyz % z
elif (len(z) == formatxyzshort_size):
print formatxyzshort % z
x = ncfile.variables['cell_angles'][frame]
y = ncfile.variables['cell_lengths'][frame]
#text_file.close()
# program starts - generation of file name
for md in range(1,3):
if md < 10:
for pico in range(100,1100, 100):
if pico >= 1000:
kkk = "waters1445-MD00{0}-run{1}.traj".format(md,pico)
loops(kkk)
elif pico < 1000:
kkk = "waters1445-MD00{0}-run0{1}.traj".format(md,pico)
loops(kkk)
#print kkk
At the (# program starts - generation of file name) line, the code supposed to generate the file name and accordingly call the function and extract the velocity and dump the values in (text_file = open("Output.mmm.dat", "a")
When execute this code, the program is running, but unfortunately could not produce output files according the input trajectory file names.
I want the output file names to be:
velo-waters1445-MD001-run0100.dat
velo-waters1445-MD001-run0200.dat
velo-waters1445-MD001-run0300.dat
velo-waters1445-MD001-run0400.dat
velo-waters1445-MD001-run0500.dat
.
.
.
I could not trace where I need to do changes.
Your code's indentation is broken: The first assignment to formatxyz and the following code is not aligned to either the def grouper, nor the for FRAMES.
The main problem may be (like Johannes commented on already) the time when you open the file(s) for writing and when you actually write data into the file.
Check:
for FRAMES in range(0,200):
frame = FRAMES
text_file = open("Output.mmm.dat", "a")
The output file is named (hardcoded) Output.mmm.dat. Change to "Output.{0}.dat".format(mmm). But then, the variable mmm never changes inside the loop. This may be ok, if all frames are supposed to be written to the same file.
Generally, please work on the names you choose for variables and functions. loops is very generic, and so are kkk and mmm. Be more specific, it helps debugging. If you don't know what's happening and where your programs go wrong, insert print("dbg> do (a)") statements with some descriptive text and/or use the Python debugger to step through your program. Especially interactive debugging is essential in learning a new language and new concepts, imho.