argparse read in txt file - python-3.x

I am trying to read a text file. In the second step I loop through the files and then I am trying to show the results in the command line.
I have a couple of problems:
I am not sure whether I managed to read in the text file, there is no error message, but
the outcome does not come
I get an error "UnboundLocalError: local variable 'P' referenced before assignment - although
I defined the variables before the function
The function works and prints the desired value but not when running it in the command line
with argparse
The code runs as "python filename.py textfile" in the command line
Checking other threads on agrparse did not help.
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('filename')
args = parser.parse_args()
A = 0 # the number of characters are 0 in the beginning
B = 0
C = 0
D = 0
with open(args.filename) as file:
def rooms():
with open("rooms.txt", "r") as in_file:
lines = in_file.readlines()
for line in lines:
if "A" in line:
W+=line.count("A") #I use the count method to count each character in a specific row
if "B" in line:
B+=line.count("B")
if "C" in line:
C+=line.count("C")
if "D" in line:
D+=line.count("D")
rooms()
# if __name__=='main__main':
print(f'total:\nA: {A} B: {B} C: {C} D: {D}')
Any help would be appreciated

There are many issues with the code if it is full code:
1)indentation : Not clear indentation in your code, so it is not executed as intended.
2)syntax: There should be at least 2 blank lines after completing your function code, so that code goes into function.
3)Separate out your function definition & function call. Create your function definition (def rooms()) outside file open.

You have some issues with you code, some of which is mentioned by KiranM's answer.
Other issues are:
You have two different sources for accepting files, argsparse and a hard coded filename.
You can accomplish want you want with a dictionary and if statement.
You read in the lines twice, with the for loop and in_file.readlines().
def room(filename::str): # or a Path object.
letters = {"A":0, "B":0, "C":0, "D":0}
with open(filename, "r") as in_file:
for line in in_file:
if line in letters:
letters[line] = letters[line] + 1
return letters
# In main:
print(room("room.txt"))

Related

Find, multiply and replace numbers in strings, by line

I'm scaling the Gcode for my CNC laser power output. The laser's "S" value maxes at 225 and the current file scale is 1000. I need to multiply only/all S values by .225, omit S values of 0, and replace in the string for each line. There are pre-designated "M", "G", "X", "Y", "Z", "F", and "S" in the Gcode for axis movement and machine functions.
Note: I can't do this manually as there's like 7.5k lines of code.
Hoping for .py with an outcome like (top 3 lines):
Old> G1Y0.1S0 New> G1Y0.1S0
Old> G1X0.1S248 New> G1X0.1S55.8
Old> G1X0.1S795.3 New> G1X0.1S178.9
Example file Code:
G1Y0.1S0
G1X0.1S248
G1X0.1S795.3
G1X0.2S909.4
G1X0.1S874
G1X0.1S374
G1X1.1S0
G1X0.1S610.2
G1X0.1S893.7
G1X0.6S909.4
G1X0.1S893.7
G1X0.1S661.4
G1X0.1S157.5
G1X0.1Y0.1S0
G1X-0.1S66.9
G1X-0.1S539.4
G1X-0.2S909.4
G1X-0.1S897.6
G1X-0.1S811
G1X-0.1S515.7
G1X-0.1S633.9
G1X-0.1S874
G1X-0.3S909.4
G1X-0.1S326.8
G1X-0.8S0
Tried this:
import os
import sys
import fileinput
print("Text to Search For:")
textToSearch = input("> ")
print("Set Max Power Output:")
valueMult = input("> ")
print("File to work:")
fileToWork = input("> ")
tempFile = open(fileToWork, 'r+')
sValue = int
for line in fileinput.input (fileToWork):
if textToSearch in line:
c = str(textToSearch,(sValue)) #This is where I'm stuck.
print("Match Found >> ", sValue)
else:
print("Match Not Found")
tempFile.write(line.replace(textToSearch, (sValue,"(sValue * (int(valueMult)/1000))")))
tempFile.close()
#input("\n\n Press Enter to Exit")
Output:
Text to Search For:
> S
Set Max Power Output:
> 225
File to work:
> test.rtf
Match Not Found
Traceback (most recent call last):
File "/Users/iamme/Desktop/ConvertGcode.py", line 25, in <module>
tempFile.write(line.replace(textToSearch, (sValue,"(sValue * (int(valueMult)/1000))")))
TypeError: replace() argument 2 must be str, not tuple
>>>
test.rtf file:
Hello World
X-095Y15S434.5
That is Solid!
Your code has a couple of issues that need to be addressed:
first, you declare the sValue variable but never assign it the value from every line in your loop,
second, said variable is an int, but should be a float or you'll lose the decimal part seen in the file,
and third, since you're not getting the corresponding values, you're not multiplying the aforementioned values by the new scale factor to then replace the old with this.
Additionally, you're opening the original file in read/write mode (r+), but I would recommend you write to a new file instead.
Now, here is your code with fixes and changes (I'm taking the liberty to write variable names in Python style):
multiplier = input("New max power output for S: ")
input_file = input("Input file: ")
output_file = input("Output file: ")
with open(input_file, 'r') as source, open(output_file, 'w') as target:
for line in source:
if 'S' in line:
line = line.removesuffix('\n')
split_line = line.split('S', -1)
new_value = float(split_line[1]) * float(multiplier)
new_line = f'{split_line[0]}S{new_value:.1f}\n'
print(f'Old> {line:25s}New> {new_line}', end='')
target.write(new_line)
else:
target.write(line)
As you can see, we open both source and target files at the same time. By using the with statement, the files are closed at the end of that block.
The code assumes the text to search will appear no more than once per line.
When a match is found, we need to remove the newline from the line (\n) so it's easy to work with the number after the S. We split the line in two parts (stored in the list split_line), and convert the second element (S's value) to a float and multiply it by the entered multiplier. Then we construct the new line with its new value, print the old and new lines, and write it to the target file. We also write the line to the target file when a match isn't found so we don't lose them.
IMPORTANT: this code also assumes no additional values appear after S{value} in the lines, as per your sample. If that is not the case, this code will fail when reaching those lines.

How do I find multiple strings in a text file?

I need all the strings found in the text file to be found and capitalized. I have found out how to find the string but getting multiple is my issue if you can help me print, where the given string is throughout my code, would be great thanks.
import os
import subprocess
i = 1
string1 = 'biscuit eater'
# opens the text file
# if this is the path where my file resides, f will become an absolute path to it
f = os.path.expanduser("/users/acarroll55277/documents/Notes/new_myfile.txt")
# with this form of open, the wile will automatically close when exiting the code block
txtfile = open (f, 'r')
# print(f.read()) to print the text document in terminal
# this sets variables flag and index to 0
flag = 0
index = 0
# looks through the file line by line
for line in txtfile:
index += 1
#checking if the sting is in the line or not
if string1 in line:
flag = 1
break
# checking condition for sting found or not
if flag == 0:
print('string ' + string1 + ' not found')
else:
print('string ' + string1 + ' found in line ' + str(index))
I believe your approach would work, but it is very verbose and not very Pythonic. Try this out:
import os, subprocess
string1 = 'biscuit eater'
with open(os.path.expanduser("/users/acarroll55277/documents/Notes/new_myfile.txt"), 'r+') as fptr:
matches = list()
[matches.append(i) for i, line in enumerate(fptr.readlines()) if string1 in line.strip()]
fptr.read().replace(string1, string1.title())
if len(matches) == 0: print(f"string {string1} not found")
[print(f"string {string1} found in line {i}") for i in matches]
This will now print out a message for every occurrence of your string in the file. In addition, the file is handled safely and closed automatically at the end of the script thanks to the with statement.
You can use the str.replace-method. So in the line where you find the string, write line.replace(string1, string1.upper(), 1). The last 1 is there to only make the function replace 1 occurence of the string.
Either that or you read the text file as a string and use the replace-method on that entire string. That saves you the trouble of trying to find the occurence manually. In that case, you can write
txtfile = open(f, 'r')
content = txtfile.read()
content = content.replace(string1, string1.upper())

Find items in a text file that is a incantinated string of capitalized words that begin with a certain capital letter in python

I am trying to pull a string of input names that get saved to a text file. I need to pull them by capital letter which is input. I.E. the saved text file contains names DanielDanClark, and I need to pull the names that begin with D. I am stuck at this part
for i in range(num):
print("Name",i+1," >> Enter the name:")
n=input("")
names+=n
file=open("names.txt","w")
file.write(names)
lookUp=input("Did you want to look up any names?(Y/N)")
x= ord(lookUp)
if x == 110 or x == 78:
quit()
else:
letter=input("Enter the first letter of the names you want to look up in uppercase:")
file=open("names.txt","r")
fileNames=[]
file.list()
for letter in file:
fileNames.index(letter)
fileNames.close()
I know that the last 4 lines are probably way wrong. It is what I tried in my last failed attempt
Lets break down your code block by block
num = 5
names = ""
for i in range(num)
print("Name",i+1," >> Enter the name:")
n=input("")
names+=n
I took the liberty of giving num a value of 5, and names a value of "", just so the code will run. This block has no problems. And will create a string called names with all the input taken. You might consider putting a delimiter in, which makes it more easier to read back your data. A suggestion would be to use \n which is a line break, so when you get to writing the file, you actually have one name on each line, example:
num = 5
names = ""
for i in range(num)
print("Name",i+1," >> Enter the name:")
n = input()
names += n + "\n"
Now you are going to write the file:
file=open("names.txt","w")
file.write(names)
In this block you forget to close the file, and a better way is to fully specify the pathname of the file, example:
file = open(r"c:\somedir\somesubdir\names.txt","w")
file.write(names)
file.close()
or even better using with:
with open(r"c:\somedir\somesubdir\names.txt","w") as openfile:
openfile.write(names)
The following block you are asking if the user want to lookup a name, and then exit:
lookUp=input("Did you want to look up any names?(Y/N)")
x= ord(lookUp)
if x == 110 or x == 78:
quit()
First thing is that you are using quit() which should not be used in production code, see answers here you really should use sys.exit() which means you need to import the sys module. You then proceed to get the numeric value of the answer being either N or n and you check this in a if statement. You do not have to do ord() you can use a string comparisson directly in your if statement. Example:
lookup = input("Did you want to look up any names?(Y/N)")
if lookup.lower() == "n":
sys.exit()
Then you proceed to lookup the requested data, in the else: block of previous if statement:
else:
letter=input("Enter the first letter of the names you want to look up in uppercase:")
file=open("names.txt","r")
fileNames=[]
file.list()
for letter in file:
fileNames.index(letter)
fileNames.close()
This is not really working properly either, so this is where the delimiter \n is coming in handy. When a text file is opened, you can use a for line in file block to enumerate through the file line by line, and with \n delimiter added in your first block, each line is a name. You also go wrong in the for letter in file block, it does not do what you think it should be doing. It actually returns each letter in the file, regardless of whay you type in the input earlier. Here is a working example:
letter = input("Enter the first letter of the names you want to look up in uppercase:")
result = []
with open(r"c:\somedir\somesubdir\names.txt", "r") as openfile:
for line in openfile: ## loop thru the file line by line
line = line.strip('\n') ## get rid of the delimiter
if line[0].lower() == letter.lower(): ## compare the first (zero) character of the line
result.append(line) ## append to result
print(result) ## do something with the result
Putting it all together:
import sys
num = 5
names = ""
for i in range(num)
print("Name",i+1," >> Enter the name:")
n = input("")
names += n + "\n"
with open(r"c:\somedir\somesubdir\names.txt","w") as openfile:
openfile.write(names)
lookup = input("Did you want to look up any names?(Y/N)")
if lookup.lower() == "n":
sys.exit()
letter = input("Enter the first letter of the names you want to look up in uppercase:")
result = []
with open(r"c:\somedir\somesubdir\names.txt", "r") as openfile:
for line in openfile:
line = line.strip('\n')
if line[0].lower() == letter.lower():
result.append(line)
print(result)
One caveat I like to point out, when you create the file, you open the file in w mode, which will create a new file every time, therefore overwriting the a previous file. If you like to append to a file, you need to open it in a mode, which will append to an existing file, or create a new file when the file does not exist.

Python Error with appending string to a file, how do I add it correctly?

I am building a function that opens a file, calculates the sum of integers on different lines, and appends the file with a new string 'Total=sum' on a new line. I am getting error: can't assign to operator on my final value. This is not a duplicate being that I edited the way the duplicate suggestion did and it is still throwing an error. Also, I need to KEEP THE TOTAL, after every iteration.
Here is my function:
def append_total(filename):
total=0
with open(filename) as contents:
for line in contents:
if line.isdigit():
total+=int(line)
else:
total=0
final='Total:'+total+end='\n'
contents.write(final)
return
There are several problems with your code.
1) statement
final = ('Total:', total, end='\n')
has invalid syntax and looks like you just removed print and replaced it with assignment to final. If you want to make string just write something like
final = 'Total:' + str(total) + '\n'
more info about string concatenation at docs
2) you are trying to write in file that was not opened in write mode and furthermore is closed after you leave with statement block. If you want to append a line in the end of existing file you can write
with open(filename, mode='a') as contents:
contents.write(final)
more info about open at docs
3) you need to remove newline symbols from lines to make str.isdigit work as expected, we can do this by using str.strip method
line.strip().isdigit()
4) your accumulated total will be lost in cases when any line is not a digit-like, we can save it from zeroing just by removing else block
Finally your function will be like
def append_total(filename):
total = 0
with open(filename) as contents:
for line in contents:
stripped_line = line.strip()
if stripped_line.isdigit():
total += int(stripped_line)
final = 'Total:' + str(total) + '\n'
with open(filename, mode='a') as contents:
contents.write(final)
(you don't need to explicitly return in the end of every function)
hey it seems to me that you have two "error" in your code:
first you try to write in a close file
second you don't open the file for writting or adding
def append_total(filename):
total=0
with open(filename) as contents:
for line in contents:
if line.isdigit():
total+=int(line)
else:
total=0
with open (filename, 'a') as contents: # a for append w for write
contents.write('Total:{}\n'.format(total))
`
In python when a function return nothing you can spare the return statement
Or if you want to be explicit say return None.
sorry didn't read all the comment but you also have a problem with total
I updated my answer
There are several Problems with your script:
final=('Total:', total, end='\n')
The syntax error comes from end='\n'. You probably rewrote a print() line, but you cannot use that syntax when creating a tuple (which is what you do now).
A better version would be:
final = 'Total:' + total + '\n'
but that would fail, because you cannot "add" a string and an int.
You could use int(total), but using the format method would be even better:
final = 'Total: {}\n'.format(total)
The next problem is, that you try to write to the file after the with block, which will lead to another error. Move the last two lines into the block as well:
def append_total(filename):
total = 0
with open(filename) as contents:
for line in contents:
if line.isdigit():
total += int(line)
else:
total = 0
final = 'Total: {}\n'.format(total)
contents.write(final)
This will still fail, because by default, files are opened read-only. You have to give open() a mode:
with open('blah.txt', 'r+') as contents:
will open the file read/writable and writes will be appended to the end (because you read the whole file before writing).
Further: the total will never be updated, because line contains a '\n' character at the end, and '1\n'.isdigit() will return False. You need to strip() the line before you use it:
line.strip().isdigit():
I also got rid of the final return, which is implicitely added by Python.

python3 opening files and reading lines

Can you explain what is going on in this code? I don't seem to understand
how you can open the file and read it line by line instead of all of the sentences at the same time in a for loop. Thanks
Let's say I have these sentences in a document file:
cat:dog:mice
cat1:dog1:mice1
cat2:dog2:mice2
cat3:dog3:mice3
Here is the code:
from sys import argv
filename = input("Please enter the name of a file: ")
f = open(filename,'r')
d1ct = dict()
print("Number of times each animal visited each station:")
print("Animal Id Station 1 Station 2")
for line in f:
if '\n' == line[-1]:
line = line[:-1]
(AnimalId, Timestamp, StationId,) = line.split(':')
key = (AnimalId,StationId,)
if key not in d1ct:
d1ct[key] = 0
d1ct[key] += 1
The magic is at:
for line in f:
if '\n' == line[-1]:
line = line[:-1]
Python file objects are special in that they can be iterated over in a for loop. On each iteration, it retrieves the next line of the file. Because it includes the last character in the line, which could be a newline, it's often useful to check and remove the last character.
As Moshe wrote, open file objects can be iterated. Only, they are not of the file type in Python 3.x (as they were in Python 2.x). If the file object is opened in text mode, then the unit of iteration is one text line including the \n.
You can use line = line.rstrip() to remove the \n plus the trailing withespaces.
If you want to read the content of the file at once (into a multiline string), you can use content = f.read().
There is a minor bug in the code. The open file should always be closed. I means to use f.close() after the for loop. Or you can wrap the open to the newer with construct that will close the file for you -- I suggest to get used to the later approach.

Resources