Python ExceptIndex issue? - python

I have a tab delimited file with 8 columns that has the following context for example
Timestamp Process TID Area Category EventID Level Message Correlation
06/21/2014 09:19:02.94 wsstracing.exe (0x068C) 0x0698 SharePoint Foundation Tracing Controller Service 5152 Information Tracing Service started.
06/21/2014 09:19:09.94 hostcontrollerservice.exe (0x063C) 0x0670 SharePoint Server Unified Logging Service b8fx High ULS Init Completed (hostcontrollerservice.exe, Microsoft.Office.Server.Native.dll)
http://pastebin.com/f9dmrQtU
The code I have currently
try:
with open('text.log') as f:
for l in f:
print(l.strip().split("\t")[5], end=" "),
print(l.strip().split("\t")[7], end=" "),
print(l.strip().split("\t")[8], end="\n")
except IndexError:
pass
Gives me
EventID Message Correlation
5152 Tracing Service started. Press any key to continue . . .
As you can see it stops after the first entry because there is nothing in the 8th column anymore.
When what I need is it to print is something like even if there is nothing under the correlation column
EventID Message Correlation
1124 blahblahblah blahblah
However when I have the following code
try:
with open('text.log') as f:
for l in f:
print(l.strip().split("\t")[5], end=" "),
print(l.strip().split("\t")[7])
but prints it in the correct format could anyone provide some assistance?

Your try is wrapped around the loop, so as soon as one error occurs that try block stop executing and jumps to the except block, meaning no more iterations can happen.
Instead, you can just put the try/except inside the for loop.
with open('text.log') as f:
for l in f:
try:
print(l.strip().split("\t")[5], end=" "),
print(l.strip().split("\t")[7], end=" "),
print(l.strip().split("\t")[8], end="\n")
except IndexError:
pass
However, since you know that there could be no 8th element, its not really exceptional and will hide errors if you have no 6th or 7th element.
Instead, try and control your logic better with:
with open('text.log') as f:
for l in f:
x = l.strip().split("\t")[5:] # Grab the elements you want...
x.pop(1) #... but remove the element you don't
print(" ".join(x)) # Now print them

Why are you wrapping the whole thing in a try block?
with open('text.log') as f:
for line in f:
txt = l.strip().split("\t") # split once
for col in (5,7,8):
try:
_end = "\n" if col == 8 else " "
print(txt[col], end=_end)
except IndexError:
print("\t", end=_end) # print a blank column

When you do the .strip() you are losing the trailing tabs, so when you split() it the line is shorter. Besides that, you are doing the same operation multiple times.
Try this instead:
with open('text.log') as f:
for l in f:
fields = l.split('\t')
print(fields[5], end=" "),
print(fields[7], end=" "),
print(fields[8], end="\n")

Related

How do I undo what I'm currently writing before close()?

for i in range(0,5):
f = open("StudentRecords.txt", "a")
try:
f.write(input("Name: ")+"\n")
f.write(str(int(input("ID: ")))+"\n")
f.write(str(float(input("GPA: ")))+"\n")
except ValueError:
print("Error: You entered a String for ID or GPA.")
f.close()
Here for example if I tried to write a string for GPA, I will catch the error and the program will move on, but the Name and ID of the same iteration will still be written
I want it to only write if all the 3 data are valid.
As the comments said, the best approach is to validate all the data before writing anything. But if you really need to undo, you can do it by saving the file position before each record, seeking back to it, and truncating to remove everything written after.
And rather than reopening the file for each record, you should open it once before the loop. Use with to close it automatically when the block is finished.
with open("StudentRecords.txt", "w") as f:
for i in range(0,5):
try:
filepos = f.tell()
f.write(input("Name: ")+"\n")
f.write(str(int(input("ID: ")))+"\n")
f.write(str(float(input("GPA: ")))+"\n")
except ValueError:
print("Error: You entered a String for ID or GPA.")
f.seek(filepos)
f.truncate()
The simple solution is to save the inputs in variables first, and then save to file.
for i in range(0,5):
f = open("StudentRecords.txt", "a")
try:
name = input("Name: ")+"\n"
ID = str(int(input("ID: ")))+"\n"
GPA = str(float(input("GPA: ")))+"\n"
f.write(name + ID + GPA)
except ValueError:
print("Error: You entered a String for ID or GPA.")
f.close()
That being said, I would suggest updating the code a little more:
for i in range(0,5):
name = input("Name: ") + "\n"
try:
ID = str(int(input("ID: "))) + "\n"
GPA = str(float(input("GPA: "))) + "\n"
with open("StudentRecords.txt", "a") as f:
f.write(name + ID + GPA)
except ValueError:
print("Error: You entered a String for ID or GPA.")
Using with means you won't have to deal with the f.close(), among other things, and so you won't forget it. And since the name = ... line doesn't seem to need a try-except block, we can move it outside.
Others have shown you a way to validate your data, but right now the program just stops if the user makes a mistake. You really want some way for them to correct their error and continue.
To put this in your main routine would require a separate loop and try/except structure for each number, which isn't too bad right now with two values, but gets unwieldy as you add more.
So instead of repeating ourselves, let's write a function that repeats until the user enters a valid number. We can pass in the type of number we want (int or float).
def inputnum(prompt, T=float):
while True:
try:
return T(input(prompt))
except ValueError:
print(">>> You entered an nvalid number. Please try again.")
Then call that function to get your numbers (combined with some other small improvements):
with open("StudentRecords.txt", "a") as f:
for i in range(5):
name = input("Name: ")
ID = inputnum("ID: ", int)
GPA = inputnum("GPA: ", float)
f.write(f"{name}\n{ID}\n{GPA}\n")

Unsure how to get user input from a multiple line loop - Python

I have been trying to create a program that lets users name, write and save documents, here is what I have come up with so far:
doc_name = str(input("Document Name: "))
end = ""
for line in iter(input, end):
document = "\n".join(iter(input, end))
pass
try:
savefile = open("/home/" +doc_name+ ".txt", "w")
savefile.write(x)
savefile.close()
print("Document - " +doc_name+ "\nSuccessfully saved.\n\n")
except:
print("An error occurred.\nUnable to save document.\n\n")
The 'for loop' I have used was from the following page:
Raw input across multiple lines in Python but I am unsure how to use the input from this loop, so I am able to save it to a textfile.
I need the input in this line of code in the place of x:
savefile.write(x)
I am using Python 3.2.3 for this program (if that helps?).
I would like to know how the user input entered during the for loop can be stored in a varible and then used at some other point in the program.
Thanks.
doc_name = input("Document Name: ") # don't need to cast to str
end = ""
result = [] # I recommend initializing a list for the lines
for line in iter(input, end): # you only need this single input call
result.append(line) # add each line to the list
try:
# using "with" in this manner is guaranteed to close the file at the end
with open("/home/" +doc_name+ ".txt", "w") as savefile:
for line in result: # go through the list of lines
# write each one, ending with a newline character
savefile.write(line + '\n')
except IOError:
print("An error occurred.\nUnable to save document.\n\n")
else: # print this if save succeeded, but it's not something we want to "try"
print("Document - " +doc_name+ "\nSuccessfully saved.\n\n")
You only need to use pass when Python expects statements (such as in an indented block) but you have no statements for it to execute - it's basically a placeholder. The common use is when you want to define your program's functions (e.g., def myfunction(a, b):) but you don't have the actual content for them yet.

For range iteration

I'm trying to iterate a certain number of lines from a text file. I've tried doing so by using different combinations of i += 1 and for loops, but it just seems to print out all of the lines from the text file.
def showEntries(amount):
print("---------- SUBSCRIPTIONS ----------\n")
with open('lib/names.txt','r') as names:
for line in names:
for x in range(0,2):
print(line)
print("---------- END OF LIST ----------")
You can use itertools.islice() for this.
from itertools import islice
def showEntries(filename, amount):
with open(filename,'r') as names:
for line in islice(names, amount):
print(line)
I think you want something like:
for line_no, line in enumerate(names):
if line_no >= amount: # if we've seen enough already
break # stop looping
print(line) # otherwise show the current line
For example:
>>> names = ["John Cleese", "Graham Chapman", "Terry Gilliam", "Eric Idle", "Terry Jones", "Michael Palin"]
>>> for index, name in enumerate(names):
if index >= 3:
break
print(name)
John Cleese
Graham Chapman
Terry Gilliam
See the docs on enumerate for more information.
I believe this is what you want to do ...
a. Get an email address as input from the user and add it to a file. As an aside ... you may want to do the following before you write it to the file...
- ensure that the email address is a valid address (use regex to enforce this)
- ensure that the email address does not exist already (you don't want a file full of duplicate addresses)
etc...
and,
b. Print out how a specified number of results from your subscriber list. You need to either put your
Here's a quick example of what you can do to read x number of lines from. I've used a lot of syntactic sugar .. which you can choose not to use..
def printLines(numlines):
i = 0
with open(file) as f:
for line in f:
if i < numlines:
print line
i += 1
else:
break
Your code is really close — you just need to let the iteration of the number of lines control the loop, not the number of them in the file:
def showEntries(amount):
print("---------- SUBSCRIPTIONS ----------\n")
with open('lib/names.txt', 'r') as names:
for _ in range(amount):
print(next(file).rstrip())
print("---------- END OF LIST ----------")
To be more robust, inner portion of the loop probably should be wrapped in a try/except to handle the case were the file contains less than the specified number of lines gracefully.

Python 2.7.2 Multiple Values for one variable

I run my own business from home and started use Python 2 days ago. I'm trying to write a script that will search through my log files line by line and tell me if a system doesn't match my mandatory naming scheme. There are multiple different schemes and I want the script to look for them all. I've tried using a list (as seen below) but that won't work and then I tried with normal brackets and that gave me an error (requires left operand, not tuple). I've noted the lines that give me a problem.
#variables
tag = ["DATA-", "MARK", "MOM", "WORK-"] #THIS ONE!!!!!!
#User Input
print "Please select Day of the week"
print "1. Monday"
print "2. Tuesday"
print "3. Wednesday"
print "4. Thursday"
print "5. Friday"
print "6. Saturday"
print "7. Sunday"
day = input("> ")
#open appropriate file and check to see if 'tag' is present in each line
#then, if it doesn't, print the line out.
if day == 1:
f = open('F:\DhcpSrvLog-Mon.log', 'r')
for line in f:
if tag in line: #THIS ONE!!!!!!!!!!!!!
pass
else:
print line
Any tips or tricks would be most appreciated!
I suggest rewriting the code like this:
with open('F:\DhcpSrvLog-Mon.log', 'rU') as f:
for line in f:
for t in tag:
if t in line: break
else:
print line
Using with you automagically close the file on exit of the block, so you needn't worry about forgetting to close it. Using else: in the for loop only triggers if you don't break out of the loop earlier.
if day == 1:
f = open('F:\DhcpSrvLog-Mon.log', 'r')
for line in f:
if tag in line: #THIS ONE!!!!!!!!!!!!!
pass
else:
print line
replace with
if day == 1:
f = open('F:\DhcpSrvLog-Mon.log', 'r')
for line in f:
if [x for x in tag if x in line]: #THIS ONE!!!!!!!!!!!!!
pass
else:
print line
use any to check this. It is more efficient because it will not try all the tags if it find that one is in line.
any(x in line for x in tag)
contains_tag=False
for t in tag:
if t in line:
contains_tag=True
break # Found a match, break out of for loop
if not contains_tag:
print (line)
First you need to loop through each of the tags (e.g. for t in tag). Then you need to check if the string t is contained in line.
Since you're only looking for one tag that does match, the simplest way is to keep track with a boolean variable.
If you wanted to only look for log messages that start with that tag, you could say if line.startswith(t) instead of if t in line

python file list search (I have two matching strings but python doesn't think they are equal)

if your input is john why isn't the if statement kicking in????
studentname.txt
john 34
paul 37
poop 45
above is whats in studentname.txt
b=a
name = input('students name : ')
list1=[]
file=open('studentname.txt','r')
for (a) in file:
list1.append(a)
b=a[:-3]
why isn't this next if statement tripping if name entered is 'john' for instance??
if name == b:
print(a)
file.close
You are picking up newlines. Depending on the os you created the file on, you'll have different new line characters. The safest way to rid yourself of this is:
a = a.rstrip()
That will take care of any trailing whitespace.
You could also do:
for a in map(lambda x: x.rstrip(), file):
Also, don't name your variable 'file'. This is a python built-in function that you've now renamed for your script and any script that imports it.
Finally, you might prefer to handle files like this:
with open("studentname.txt", 'r') as testfile:
for item in (line.rstrip() for line in testfile):
print item
No need to close the file, the with statement controls it's scope and closes it.
Try this:
for a in file.readlines():
name, _, score = a.strip().partition(' ')
if name == b:
print(a)
It is cleaner in that it doesn't rely on a 2-digit value and is more expressive than arbitrary indexes. It also strips carriage returns and newlines.
alternatively, you can use a.strip()[:-3], which will trim all whitespace characters before taking the substring.
Your immediate problem is as others have mentioned that you are not aware of the \n at the end of your data. print and the repr built-in function are your friends; use them:
if name != b:
print repr(name), repr(b)
whereupon the cause of the problem becomes obvious.
Here is some (untested) code that illustrates better practice when handling simple data file formats like yours. It is intended to cope with blank/empty lines, unterminated last line, and real-life possibilities like:
Jack 9
Jill 100
Billy Bob 99
Decimus 1.23
Numberless
without crashing or running amok.
with open('studentname.txt','rU') as f:
for line_number, line in enumerate(f, 1):
line = line.rstrip('\n')
fields = line.split()
nf = len(fields]
if nf == 0:
continue: # blank/empty line
if nf == 1:
print('Only 1 field in line', line_number, repr(line))
continue
dataname = ' '.join(fields[:-1])
try:
datanumber = int(fields[-1])
except ValueError:
print('Invalid number', repr(fields[-1]), 'in line',
line_number, repr(line))
continue
list1.append((dataname, datanumber))
if name == dataname:
print(repr(dataname), number)
Note file.close evaluates to a method/function object, which does nothing. You need to call it: file.close(). However now that you are using the with statement, it will look after closing the file, so just delete that file.close line.

Categories