object not iterable with inputfile - python

I am basically trying to update a line in saved files with new updated number but it leaves only one line in the file. It feels like its overwriting over entire file rather than updating it. I looked at other questions here, and although they gave me right module to use I can't seem to figure out the problem I am having.
unique = 1
for line in fileinput.input('tweet log.txt', inplace=1):
if tweet_id in line: #checks if ID is unique, if it is not, needs to update it
tweet_fields = line.split(';')
old_count = tweet_fields[-2]
new_count = 'retweet=%d' % (int(tweet_retweet))
line = line.replace(old_count, new_count)
print line
unique = 0
if unique == 1: #if previous if didn't find uniqueness, appends the file
save_file = open('tweet log.txt', 'a')
save_file.write('id='+tweet_id +';'+
'timestamp='+tweet_timestamp+';'+
'source='+tweet_source+';'+
'retweet='+tweet_retweet+';'+'\n')
save_file.close()
I feel like this has a very easy solution but I am clearly missing it.
Thanks in advance!

I think the issue you're having is due to your conditional in the loop over the input. When you use fileinput.input with the inplace=1 argument, it renames the original file adding a "backup" extension (by default ".bak") and redirects standard output to a new file with the original name.
Your loop is only printing the line that you're editing. Because of this, all the non-matching lines are getting filtered out of the file. You can fix this by printing each line you iterate over, even if it doesn't match. Here's an altered version of your loop:
for line in fileinput.input('tweet log.txt', inplace=1):
if tweet_id in line:
tweet_fields = line.split(';')
old_count = tweet_fields[-2]
new_count = 'retweet=%d' % (int(tweet_retweet))
line = line.replace(old_count, new_count)
unique = 0
print line
The only change is moving the print line statement out of the if block.

Related

Find all strings in text file fitting either of two formats

So I know similar questions have been asked before, but every method I have tried is not working...
Here is the ask: I have a text file (which is a log file) that I am parsing for any occurrence of "app.task2". The following are the 2 scenarios that can occur (As they appear in the text file, independent of my code):
Scenario 1:
Mar 23 10:28:24 dasd[116] <Notice>: app.task2.refresh:556A2D:[
{name: ApplicationPolicy, policyWeight: 50.000, response: {Decision: Can Proceed, Score: 0.45}}
] sumScores:68.785000, denominator:96.410000, FinalDecision: Can Proceed FinalScore: 0.713463}
Scenario 2:
Mar 23 10:35:56 dasd[116] <Notice>: 'app.task2.refresh:C6C2FE' CurrentScore: 0.636967, ThresholdScore: 0.410015 DecisionToRun:1
The problem I am facing is that my current code below, I am not getting the entire log entry for the first case, and it is only pulling the first line in the log, not the remainder of the log entry, and it appears to be stopping at the new line escape character, which is occurring after ":[".
My Code:
all = []
with open(path_to_log) as f:
for line in f:
if "app.task2" in line:
all.append(line)
print all
How can I get the entire log entry for the first case? I tried stripping escape characters with no luck. From here I should be able to parse the list of results returned for what I truly need, but this will help! ty!
OF NOTE: I need to be able to locate these types of log entries (which will then give us either scenario 1 or scenario 2) by the string "app.task2". So this needs to be incorporated, like in my example...
Before adding the line to all, check if it ends with [. If it does, keep reading and merge the lines until you get to ].
import re
all = []
with open(path_to_log) as f:
for line in f:
if "app.task2" in line:
if re.search(r'\[\s*$', line): # start of multiline log message
for line2 in f:
line += line2
if re.search(r'^\s*\]', line2): # end of multiline log message
break
all.append(line)
print(all)
You are iterating over each each line individually which is why you only get the first line in scenario 1.
Either you can add a counter like this:
all = []
count = -1
with open(path_to_log) as f:
for line in f:
if count > 0:
all.append(line)
if count == 1:
tmp = all[-count:]
del all[-count:]
all.append("\n".join(tmp))
count -= 1
continue
if "app.task2" in line:
all.append(line)
if line.endswith('[\n'):
count = 3
print all
In this case i think Barmar solution would work just as good.
Or you can (preferably) when storing the log file have some distinct delimiter between each log entry and just split the log file by this delimiter.
I like #Barmar's solution with nested loops on the same file object, and may use that technique in the future. But prior to seeing I would have done it with a single loop, which may or may not be more readable:
all = []
keep = False
for line in open(path_to_log,"rt"):
if "app.task2" in line:
all.append(line)
keep = line.rstrip().endswith("[")
elif keep:
all.append(line)
keep = not line.lstrip().startswith("]")
print (all)
or, you can print it nicer with:
print(*all,sep='\n')

Python: How to return specific lines from a text

I am new here and new to Programming too.
I am reading Jamie Chan's Learn Python in One Day and am currently at the Practical Project section. I am trying to make python read a line from a txt file. The txt file contains a name and a number seperated by a comma,
This is the text file
Benny, 102
Ann, 100
Carol, 214
Darren, 129
I succeded in making it read the first line but the trying to print the second line by calling on the name there keeps returning a nill. When I switch the lines, the same thing occurs, it reads the name in the first line but returns nill on the name in the second file.
This is the function I tried to use to read the texts:
def getUserPoint(userName):
f = open('userScores.txt', 'r')
for line in f:
result = line.splitlines()
if userName in line:
return result
else:
return "nill"
f.close()
s = getUserPoint(input('Ann'))
print(s)
And this is the result:
nill
and this is the instructions:
Each line records the information of one user. The first value is the user’s username and the second is the user’s score.
Next, the function reads the file line by line using a for loop. Each line is then split using the split() function
Let’s store the results of the split() function in the list content.
Next, the function checks if any of the lines has the same username as the value that is passed in as the parameter. If there is, the function closes the file and returns the score beside that username. If there isn’t, the function closes the file and returns the string ‘-1’
Am terribly sorry for the long winded post.
you can use :
def getUserPoint(userName):
f = open('userScores.txt', 'r')
for line in f.readlines():
result = line.splitlines()
if userName in line:
f.close()
return result
f.close()
return "nill"
s = getUserPoint(input('Ann'))
print(s)
One problem is that you have an else statement that is matched and will immediately end the function and loop
You need to return the default result after you've looked at all lines
def getUserPoint(userName):
with open('userScores.txt') as f:
for line in f:
if userName == line.rstrip().split(',')[0]:
return line
return "nill"
Then, as shown, you either want to split the comma and check the first column, or userName in line . Otherwise, you are checking
'Ann' in ["Ann, 100", ""]
since splitlines() will split at the newline character at the end, which returns False
See below
The code takes care of closing the file.
It will return None if no match found, else 'user point' is returned
def get_user_point(user_name):
with open('userScores.txt', 'r') as f:
lines = [l.strip() for l in f]
for line in lines:
parts = line.split(',')
if user_name == parts[0]:
return parts[1]
Thanks everyone for the help...
This code by OneCricketeer worked:
def getUserPoint(userName):
with open('userScores.txt') as f:
for line in f:
if userName == line.split(',')[0]:
return line
return "nill"
Since am new to Python and programming in General, I will probably be asking a lot more questions.
Thanks for the help everyone.

How to open a file and change a line

I've looked at loads of threads on this but cant find the right answer:
I'm a bit new to python. Im opening a file in python, inserting one line before the beginning line and one before the last line and then reconstructing all the lines into a string variable at the end.
Heres the function Im trying to run on the opened file. This changes all lines where mode="0" to mode="1" or vice versa.
def Modes(file, mode):
endstring = ''
if(mode == 1):
mode0 = 'mode="0"'
mode1 = 'mode="1"'
else:
mode0 = 'mode="1"'
mode1 = 'mode="0"'
for line in iter(file):
if 'Modes' in line:
line = line.replace(mode0,mode1)
endstring += line
return endstring
So I try the following:
mode = 1
input_file = open("c:\myfile.txt")
input_file.readlines()
lengthlines = len(input_file)
#insert line at position 1
input_file.insert(1,'<VARIABLE name="init1" />')
#insert line at last line position - 1
input_file.insert(lengthlines,'<VARIABLE name="init2" />')
#join the lines back up again
input_file = "".join(input_file)
#run the modes function - to replace all occurrences of mode=x
finalfile = Modes(input_file,mode)
print finalfile
And then Im getting the error, "object of type file, has no "len()"" and general object/list errors.
It seems Im getting objects/lists etc mixed up but im not sure where - would be grateful for any assistance - cheers
input_file.readlines() returns the content but does not assign it to input_file.
You'll have to assign the return value of the call to a variable, like so:
file_content = input_file.readlines()
and then pass that to len()
lengthlines = len(file_content)
EDIT: solving the issue with len() leads to further exceptions.
This should roughly do what you want:
mode = 1
with open("c:\myfile.txt") as input_file:
file_content = list(input_file.readlines())
file_content.insert(0,'<VARIABLE name="init1" />')
file_content.append('<VARIABLE name="init2" />')
finalfile = Modes(file_content,mode)
print finalfile
You might have to alter your string concatenation in the function if you want to stick with several lines.
endstring += line + '\n'
return endstring.rstrip('\n')
This does not yet write the new content back to the file though.
EDIT2: And it is always good practice to close the file when you are done with it, therefore I updated the above to use a context manager that takes care of this. You could also explicitly call input_file.close() after you are finished.

Splitting a line from a file into different lists

My program is supposed to take input from the user and read a file with the name input. Read file gets saved into a dictionary called portfolio and from there all I have to do is sort each line in the portfolio into keys and values.
Here's my code.
portfolio = {}
portfolio = file_read() #Reads the file through a function
if file_empty(portfolio) == True or None: #nevermind this, it works
print "The file was not found."
else:
print "The file has successfully been loaded"
for line in portfolio:
elements = line.strip().split(",") #separate lists by comma
print elements[0] #using this to check
print elements[1] #if it works at all
All this does is print the first letter in the first line, which is S. And apparently elements[1] is supposed to be the second letter but index is out of range, please enlighten me what might be wrong.
Thank you.
It looks like file_read() is reading the file into a string.
Then for line in portfolio: is iterating through each character in that string.
Then elements = line.strip().split(",") will give you a list containing one character, so trying to get elements[1] is past the bounds of the list.
If you want to read the whole contents of the file into a string called portfolio, you can iterate through each line in the string using
for line in porfolio.split('\n'):
...
But the more usual way of iterating through lines in a file would be
with open(filename,'r') as inputfile:
for line in inputfile:
....
Got it to work with this code:
for line in minfil :
line = line.strip()
elements = line.split(",")
portfolio[str(elements[0])] = [(int(elements[1]),float(elements[2]), str(elements[3]))]

Python- how to use while loop to return longest line of code

I just started learning python 3 weeks ago, I apologize if this is really basic. I needed to open a .txt file and print the length of the longest line of code in the file. I just made a random file named it myfile and saved it to my desktop.
myfile= open('myfile', 'r')
line= myfile.readlines()
len(max(line))-1
#the (the "-1" is to remove the /n)
Is this code correct? I put it in interpreter and it seemed to work OK.
But I got it wrong because apparently I was supposed to use a while loop. Now I am trying to figure out how to put it in a while loop. I've read what it says on python.org, watched videos on youtube and looked through this site. I just am not getting it. The example to follow that was given is this:
import os
du=os.popen('du/urs/local')
while 1:
line= du.readline()
if not line:
break
if list(line).count('/')==3:
print line,
print max([len(line) for line in file(filename).readlines()])
Taking what you have and stripping out the parts you don't need
myfile = open('myfile', 'r')
max_len = 0
while 1:
line = myfile.readline()
if not line:
break
if len(line) # ... somethin
# something
Note that this is a crappy way to loop over a file. It relys on the file having an empty line at the end. But homework is homework...
max(['b','aaa']) is 'b'
This lexicographic order isn't what you want to maximise, you can use the key flag to choose a different function to maximise, like len.
max(['b','aaa'], key=len) is 'aaa'
So the solution could be: len ( max(['b','aaa'], key=len) is 'aaa' ).
A more elegant solution would be to use list comprehension:
max ( len(line)-1 for line in myfile.readlines() )
.
As an aside you should enclose opening a file using a with statement, this will worry about closing the file after the indentation block:
with open('myfile', 'r') as mf:
print max ( len(line)-1 for line in mf.readlines() )
As other's have mentioned, you need to find the line with the maximum length, which mean giving the max() function a key= argument to extract that from each of lines in the list you pass it.
Likewise, in a while loop you'd need to read each line and see if its length was greater that the longest one you had seen so far, which you could store in a separate variable and initialize to 0 before the loop.
BTW, you would not want to open the file with os.popen() as shown in your second example.
I think it will be easier to understand if we keep it simple:
max_len = -1 # Nothing was read so far
with open("filename.txt", "r") as f: # Opens the file and magically closes at the end
for line in f:
max_len = max(max_len, len(line))
print max_len
As this is homework... I would ask myself if I should count the line feed character or not. If you need to chop the last char, change len(line) by len(line[:-1]).
If you have to use while, try this:
max_len = -1 # Nothing was read
with open("t.txt", "r") as f: # Opens the file
while True:
line = f.readline()
if(len(line)==0):
break
max_len = max(max_len, len(line[:-1]))
print max_len
For those still in need. This is a little function which does what you need:
def get_longest_line(filename):
length_lines_list = []
open_file_name = open(filename, "r")
all_text = open_file_name.readlines()
for line in all_text:
length_lines_list.append(len(line))
max_length_line = max(length_lines_list)
for line in all_text:
if len(line) == max_length_line:
return line.strip()
open_file_name.close()

Categories