Why does my program ask for input that comes second? - python

So I've written a simple program that allows user to enter a line they would like to edit and text they would like to put into that line
def edit_line(file):
a_file = open(file, 'r')
list_of_lines = a_file.readlines()
list_of_lines[int(input('What line would you like to edit?: ')) - 1] = input('Write your text here: ') + '\n'
a_file = open(file, 'w')
a_file.writelines(list_of_lines)
a_file.close()
edit_line('sample.txt')
When I run the program it works fine. However, It asks the user to input the text first and the line number second.
What is the reason for this and how can I fix it?

If you want to fix the problem, just split the one line into two:
Instead of:
list_of_lines[int(input('What line would you like to edit?: ')) - 1] = input('Write your text here: ') + '\n'
Do:
index = int(input('What line would you like to edit?: ')) - 1
list_of_lines[index] = input('Write your text here: ') + '\n'
And as the answer #Guy linked explains, when you are doing an assignment line of code, the right hand (value of the variable) is run before the left side.

Validation is everything! What would happen if the user's input for the line number wasn't within the range of lines read from the file?
Here's a more robust approach:
def edit_line(filename):
with open(filename, 'r+') as file:
lines = file.readlines()
while True:
try:
lineno = int(input('What line would you like to edit: '))
if 0 <= lineno < len(lines):
lines[lineno] = input('Write your text here: ') + '\n'
file.seek(0)
file.writelines(lines)
file.truncate()
break
else:
raise ValueError('Line number out of range')
except ValueError as e:
print(e)
edit_line('edit.txt')

Related

Outputting email address from text files in Python, looking to make code a little more elegant

I'm working on a Python course on Coursera. One of the assignments is to read input from a text file, extract the email addresses on lines starting with "From:", and then print both email addresses and the number of lines that start with "From:". I got it to work after a little effort, but I wanted to see if my code can be cleaned up.
If I shouldn't worry so much about writing elegant code if I'm just in my second week of Python, you can go ahead and let me know.
fname = input("Enter file name: ")
if len(fname) < 1:
fname = "mbox-short.txt"
fh = open(fname)
text = fh.read()
lines = text.splitlines()
count = 0
from_lines = list()
for line in lines:
if 'From:' in line:
count += 1
from_lines.append(line)
email = list()
for line in from_lines:
email = line.split()
print(email[1])
print("There were", count, "lines in the file with From as the first word")
You can get the work done with only one loop like this:
fname = input("Enter file name: ")
if len(fname) < 1:
fname = "mbox-short.txt"
fh = open(fname)
lines = text.readlines() #readlines creates a list of lines from the file
count = 0
for line in lines:
if 'From:' in line:
count += 1
email = line.split()[1]
print(email)
fh.close() # always close the file after use
print("There were {} lines in the file with From as the first word".format(count))
You never close the file. Anyway you shouldn't be handling the files manually, and instead use a context manager:
with open(fname) as as fh:
...
If you are going to iterate the file line-by-line, there is no need to save to memory the whole content of the file to a string. Files are iterators themselves and iterating over them gives the lines:
for line in fh:
There is no need for two loops - if you just found there is an email in a line, why save it for later? Just use it right there!
You might check if the line startswith instead of using in.
All together might give:
fname = input("Enter file name: ")
if len(fname) < 1:
fname = "mbox-short.txt"
count = 0
with open(fname) as fh:
for line in fh:
if line.startswith('From:'):
count += 1
email = line.split()[1]
print(email)
print("There were", count, "lines in the file with From as the first word")
Here:
fname = input("Enter file name: ")
if not(fname): fname = "mbox-short.txt"
with open(fname) as fh:
lines = fh.readlines()
count = 0
from_lines = [line for line in lines if line.startswith('From:')]
for line in from_lines:
count += 1
email = line.split()
print(email[1])
print("There were",count,"lines in the file with From as the first word")
Or...
fname = input("Enter file name: ")
if not(fname): fname = "mbox-short.txt"
with open(fname) as fh:
lines = fh.readlines()
from_lines = [line for line in lines if line.startswith('From:')]
for line in from_lines: print(line.split()[1])
print(f"There were {len(from_lines)} lines in the file with From as the first word")

reading and deleting lines in python

I am trying to read all the lines in a specific file, and it prints the number of the line as an index.
What I am trying to do is to delete the line by inputting the number of the line by the user.
As far as it is now, it prints all the lines with the number of that line, but when I enter the number of the line to be deleted, it's not deleted.
This is the code of the delete function:
def deleteorders ():
index = 0
fh = open ('orders.txt', 'r')
lines = fh.readlines()
for line in lines:
lines = fh.readlines()
index = index+1
print (str(index) + ' ' + line)
try:
indexinp = int(input('Enter the number of the order to be deleted, or "B" to go back: '))
if indexinp == 'B':
return
else:
del line[indexinp]
print (line)
fh = open ('orders.txt', 'w')
fh.writelines(line)
fh.close()
except:
print ('The entered number is not in the range')
return
This should work (you'll need to add the error handling back in):
lines = enumerate(open('orders.txt'))
for i, line in lines:
print i, line
i = int(input(">"))
open('orders.txt', 'w').write(''.join((v for k, v in lines if k != i)))

How to get my python code to go back into the loop after the exception is thrown

I'm a beginner in python & am having some problems with the structure of my homework assignment; my assignment is: "Write a program that asks the user for a filename, opens the file and reads through the file just once before reporting back to the user the number of characters (including spaces and end of line characters), the number of words, and the number of lines in the file.
If the user enters the name of a file that doesn't exist, your program should give her as many tries as she needs in order to type a valid filename. Obtaining a valid filename from the user is a common operation, so start by writing a separate, reusable function that repeatedly asks the user for a filename until she types in a file that your program is able to open."
And, I didn't start that way (& now I'm wondering if with the way I've structured it with "with/as", there's a way to even do that but my problem right now is getting it to go back into the try section of code after the error is thrown (I missed the class where this was explained so I've only ever read about this so I Know I'm not doing something right). I can get it to work as long as it's a filename that exists, if it's not, it prints nothing to the screen. Here's my code:
filename = input("please enter a file name to process:")
lineCount = 0
wordCount = 0
charCount = 0
try:
with open(filename, 'r') as file:
for line in file:
word = line.split()
lineCount = lineCount + 1
wordCount = wordCount + len(word)
charCount = charCount + len(line)
print("the number of lines in your file is:", lineCount)
print("the number of words in your file is", wordCount)
print("the number of characters in your file is:", charCount)
except OSError:
print("That file doesn't exist")
filename = input("please enter a file name to process:")
And, I'm not sure what I should do- if I should scrap this whole idea for a simple try: open(filename, 'r') / except: function of it=f there's anyway to salvage this.
So, I thought to fix it this way:
def inputAndRead():
"""prompts user for input, reads file & throws exception"""
filename = None
while (filename is None):
inputFilename = input("please enter a file name to process")
try:
filename = inputFilename
open(filename, 'r')
except OSError:
print("That file doesn't exist")
return filename
inputAndRead()
lineCount = 0
wordCount = 0
charCount = 0
with open(filename, 'r') as file:
for line in file:
word = line.split()
lineCount = lineCount + 1
wordCount = wordCount + len(word)
charCount = charCount + len(line)
print("the number of lines in your file is:", lineCount)
print("the number of words in your file is", wordCount)
print("the number of characters in your file is:", charCount)
But, I'm getting error: NameError: name 'file' is not defined
I would reorganize this code so that the file is opened in a loop. No matter how many times the user enters an invalid filename, the code will just ask for a new one and try again.
lineCount = 0
wordCount = 0
charCount = 0
f = None
while f is None:
filename = input("please enter a file name to process:")
try:
f = open(filename)
except OSError:
print("That file doesn't exist")
for line in file:
word = line.split()
lineCount = lineCount + 1
wordCount = wordCount + len(word)
charCount = charCount + len(line)
print("the number of lines in your file is:", lineCount)
print("the number of words in your file is", wordCount)
print("the number of characters in your file is:", charCount)
Write an infinite loop while True. When the file name is correct, at the end of the try, add a break.
Glad that helps

How do you get python to print line with most words in and stop repeating print?

a=input("Please enter your problem?")
problem = a.split(' ')
max_num, current_num = 0,0
chosen_line = ''
with open('solutions.txt', 'r') as searchfile:
for line in searchfile:
for word in problem:
if word in line:
current_num+=1
if current_num>max_num:
max_num=current_num
chosen_line = line
print (chosen_line)
else:
print ("please try again")
This code prints all the lines in the text file however I need it only to print the line with most words, that the user has entered in. Also if it doesn't find any words that the user has entered in the it should display 'please try again', however it displays it 7 times
You are currently accumulating a counter of how many relevant words a line contains, then saving that value in a different counter and printing the line. Instead, you will need to count words in each line and save the line with the best result so that you can print it at the end.
a = input("Please enter your problem?")
problem = set(a.split())
max_relevance = 0
best_line = ''
with open('solutions.txt') as searchfile:
for line in searchfile:
relevance = sum(word in problem for word in line.split())
if relevance > max_relevance:
best_line = line
print(best_line or "please try again")
a=input("Please enter your problem?")
problem = set(a.split(' '))
max_num, current_num = 0,0
chosen_line = ''
with open('solutions.txt', 'r') as searchfile:
for line in searchfile:
current_num = sum( 1 for item in line if item in problem)
if current_num > max_num:
chosen_line = line
max_num = current_num
print chosen_line

Using the split() or find() function in python

Am writing a program that opens a file and looks for line which are like this:
X-DSPAM-Confidence: 0.8475.
I want to use the split and find function to extract these lines and put it in a variable. This is the code I have written:
fname = raw_input("Enter file name: ")
if len(fname) == 0:
fname = 'mbox-short.txt'
fh = open(fname,'r')
total = 0
for line in fh:
if not line.startswith("X-DSPAM-Confidence:"): continue
Please, Please I am now beginning in python so please give me something simple which I can understand to help me later on. Please, Please.
I think the only wrong part is not in if :
fname = raw_input("Enter file name: ")
if len(fname) == 0:
fname = 'mbox-short.txt'
fh = open(fname,'r')
total = 0
lines = []
for line in fh:
if line.startswith("X-DSPAM-Confidence:"):
lines.append(line)
First receive the input with raw_input()
fname = raw_input("Enter file name: ")
Then check if the input string is empty:
if not fname:
fname = 'mbox-short.txt'
Then, open the file and read it line by line:
lines = []
with open(fname, 'r') as f:
for line in f.readlines():
if line.startswith("X-DSPAM-Confidence:"):
lines.append(line)
The with open() as file statement just ensures that the file object gets closed when you don't need it anymore. (file.close() is called automatically upon exiting out of the with clause)
I know where this one is coming from as I've done it myself some time ago. As far as I remember you need to calculate the average :)
fname = raw_input("Enter file name: ")
fh = open(fname)
count = 0
sum = 0
for line in fh:
if not line.startswith("X-DSPAM-Confidence:") : continue
count = count + 1
pos = line.find(' ')
sum = sum + float(line[pos:])
average = sum/count
You're very close, you just need to add a statement below the continue adding the line to a list.
fname = raw_input("Enter file name: ")
if len(fname) == 0:
fname = 'mbox-short.txt'
fh = open(fname,'r')
total = 0
lines = []
for line in fh:
if not line.startswith("X-DSPAM-Confidence:"):
continue
lines.append(line) # will only execute if the continue is not executed
fh.close()
You should also look at the with keyword for opening files - it's much safer and easier. You would use it like this (I also swapped the logic of your if - saves you a line and a needless continue):
fname = raw_input("Enter file name: ")
if len(fname) == 0:
fname = 'mbox-short.txt'
total = 0
good_lines = []
with open(fname,'r') as fh:
for line in fh:
if line.startswith("X-DSPAM-Confidence:"):
good_lines.append(line)
If you just want the values, you can do a list comprehension with the good_lines list like this:
values = [ l.split()[1] for l in good_lines ]

Categories