Changing a file line - Python - python

I've a file entitled 'users.txt' with the following structure; username:info_about_the_user.
Something like this:
users.txt:
mark:stuffabouthim anthony:stuffabouthim peter:stuffabouthim peterpeter:stuffabouthim peterpeterpeter:stuffabouthim peterpeterpeterpeter:stuffabouthim
The following part of the script needs to change a line (change info about an user) but I'm having problems when the string is duplicated (peter - peterpeter) and I dont know how to fix it.
def test():
fn = 'users.txt'
f = open(fn)
output = []
changeuser = 'peterpeter'
userinfo = 'HeIsTall'
for line in f:
if not changeuser+":" in line:
output.append(line)
f.close()
f = open(fn, 'w')
f.writelines(output)
f.close()
f = open("users.txt", "a")
f.write(changeuser + ":" + userinfo+"\n")
f = open("users.txt", "a")
test()
This is the input I have:
Input: users.txt:
mark:stuffabouthim anthony:stuffabouthim peter:stuffabouthim peterpeter:HesAwesome peterpeterpeter:stuffabouthim peterpeterpeterpeter:stuffabouthim
I want to change info about peterpeter and have the following output:
Output I want to have: users.txt:
mark:stuffabouthim anthony:stuff about him peter:stuffabouthim peterpeter:HeIsTall peterpeterpeter:stuffabouthim peterpeterpeterpeter:stuffabouthim
But this is the input I'm having. All the lines behind peterpeter are getting deleted among other things.
mark:stuffabouthim
anthony:stuffabouthim
peter:stuffabouthim
peterpeter:HeIsTall
Can anyone give me a help with the code below to have the desired output? Thanks.

You can have it the easy way with the fileinput module:
import fileinput
def test():
fn = 'users.txt'
changeuser = 'peterpeter'
newinfo = 'HeIsTall'
for line in fileinput.input(fn, inplace=1):
user, oldinfo = line.split(':')
print '%s:%s' % (user, newinfo if user == changeuser else oldinfo.replace('\n', ''))
if __name__ == "__main__":
test()

try this:
def test():
fn = 'users.txt.txt'
f = open(fn)
output = []
changeuser = 'peterpeter'
userinfo = 'HeIsTall'
for line in f:
if line.strip().split(':')[0]!=changeuser:
output.append(line)
else:
output.append(changeuser + ":" + userinfo+"\n")
f.close()
f = open(fn, 'w')
f.writelines(output)
f.close()
test()
output:
mark:stuffabouthim
anthony:stuffabouthim
peter:stuffabouthim
peterpeter:HeIsTall
peterpeterpeter:stuffabouthim
peterpeterpeterpeter:stuffabouthim

You got a logical error in the if-clause, which DELETES all peters*, the only peter remaining is the one you append to the file.
for line in f:
if not changeuser+":" in line: #THAT MEANS ALL PETERS ARE IGNORED!
output.append(line)
It's generaly easier to understand positive clauses then a negation:
for line in f:
if changeuser+":" in line:
output.append('%s:%s\n' %(changeuser,userinfo))
else:
output.append(line)
Good code is easy to read. Try to code like you would try to write a report! That leads automatically to spliting your code into smaller pieces like functions. e.g.:
lines = read_all_lines_from_file(filename)
change_user_info(lines, user, userinfo)
save_lines_to_file(lines, filename)
Your code gets split into smaller pieces and if an error occurs you can pin it down to a few lines of code instead of having to work over several pages. ;-)

Related

Check if a variable string exist in a text file

So guys, i'm tryng to make a password generator but i'm having this trouble:
First, the code i use for tests:
idTest= "TEST"
passwrd= str(random.randint(11, 99))
if not os.path.exists('Senhas.txt'):
txtFileW = open('Senhas.txt', 'w')
txtFileW.writelines(f'{idTest}: {passwrd}\n')
txtFileW.close()
else:
txtFileA = open('Senhas.txt', 'a')
txtFileA.write(f'{idTest}: {passwrd}\n')
txtFileA.close()
print(f'{idTest}: {passwrd}')
Well, what i'm expecting is something like this:
else:
with open('Senhas.txt', 'r+') as opened:
opened.read()
for lines in opened:
if something == idTest:
lines.replace(f'{something}', f'{idTest}')
else:
break
txtFileA = open('Senhas.txt', 'a')
txtFileA.write(f'{idTest}: {passwrd}\n')
txtFileA.close()
print(f'{idTest}: {passwrd}')
I've searched for it but all i've found are ways to separate it in 2 files (for my project it doesn't match) or with "static" strings, that doesn't match for me as well.
You can use the fileinput module to update the file in place.
import fileinput
with fileinput.input(files=('Senhas.txt'), inplace=True) as f:
for line in f:
if (line.startswith(idTest+':'):
print(f'{idTest}: {passwrd}')
else:
print(line)

Update Txt file in python

I have a text file with names and results. If the name already exists, only the result should be updated. I tried with this code and many others, but without success.
The content of the text file looks like this:
Ann, 200
Buddy, 10
Mark, 180
Luis, 100
PS: I started 2 weeks ago, so don't judge my bad code.
from os import rename
def updatescore(username, score):
file = open("mynewscores.txt", "r")
new_file = open("mynewscores2.txt", "w")
for line in file:
if username in line:
splitted = line.split(",")
splitted[1] = score
joined = "".join(splitted)
new_file.write(joined)
new_file.write(line)
file.close()
new_file.close()
maks = updatescore("Buddy", "200")
print(maks)
I would suggest reading the csv in as a dictionary and just update the one value.
import csv
d = {}
with open('test.txt', newline='') as f:
reader = csv.reader(f)
for row in reader:
key,value = row
d[key] = value
d['Buddy'] = 200
with open('test2.txt','w', newline='') as f:
writer = csv.writer(f)
for key, value in d.items():
writer.writerow([key,value])
So what needed to be different mostly is that when in your for loop you said to put line in the new text file, but it's never said to Not do that when wanting to replace a score, all that was needed was an else statement below the if statement:
from os import rename
def updatescore(username, score):
file = open("mynewscores.txt", "r")
new_file = open("mynewscores2.txt", "w")
for line in file:
if username in line:
splitted = line.split(",")
splitted[1] = score
print (splitted)
joined = ", ".join(splitted)
print(joined)
new_file.write(joined+'\n')
else:
new_file.write(line)
file.close()
new_file.close()
maks = updatescore("Buddy", "200")
print(maks)
You can try this, add the username if it doesn't exist, else update it.
def updatescore(username, score):
with open("mynewscores.txt", "r+") as file:
line = file.readline()
while line:
if username in line:
file.seek(file.tell() - len(line))
file.write(f"{username}, {score}")
return
line = file.readline()
file.write(f"\n{username}, {score}")
maks = updatescore("Buddy", "300")
maks = updatescore("Mario", "50")
You have new_file.write(joined) inside the if block, which is good, but you also have new_file.write(line) outside the if block.
Outside the if block, it's putting both the original and fixed lines into the file, and since you're using write() instead of writelines() both versions get put on the same line: there's no \n newline character.
You also want to add the comma: joined = ','.join(splitted) since you took the commas out when you used line.split(',')
I got the result you seem to be expecting when I put in both these fixes.
Next time you should include what you are expecting for output and what you're giving as input. It might be helpful if you also include what Error or result you actually got.
Welcome to Python BTW
Removed issues from your code:
def updatescore(username, score):
file = open("mynewscores.txt", "r")
new_file = open("mynewscores2.txt", "w")
for line in file.readlines():
splitted = line.split(",")
if username == splitted[0].strip():
splitted[1] = str(score)
joined = ",".join(splitted)
new_file.write(joined)
else:
new_file.write(line)
file.close()
new_file.close()
I believe this is the simplest/most straightforward way of doing things.
Code:
import csv
def update_score(name: str, score: int) -> None:
with open('../resources/name_data.csv', newline='') as file_obj:
reader = csv.reader(file_obj)
data_dict = dict(curr_row for curr_row in reader)
data_dict[name] = score
with open('../out/name_data_out.csv', 'w', newline='') as file_obj:
writer = csv.writer(file_obj)
writer.writerows(data_dict.items())
update_score('Buddy', 200)
Input file:
Ann,200
Buddy,10
Mark,180
Luis,100
Output file:
Ann,200
Buddy,200
Mark,180
Luis,100

File Input/Output Error?

can anyone tell me what is wrong with my code?
def count_letters(in_file, out_file):
in_file = open("in_file.txt", "r")
for line in in_file:
for x in sorted(line):
count = x.count()
out_file = open("out_file.txt", "w")
print(x, " ", count)
in_file.close()
out_file.close()
print(out_file)
it's supposed to
Takes two filenames (in_file and out_file)as arguments
Opens and reads the input file specified by in_file, and counts the number of occurrences of each letter (in a case-insensitive manner)
Writes the result in the output file specified by out_file
when I run it, it tells me that "in_file" is not defined, but I have defined it, and made an "in_file.txt."
any help would be appreciated!
You want pass "in_file.txt" as in_file variable and use it like:
in_f=open(in_file,"r")
similarly for out_file otherwise, what is the point of making a function?
But i think your error relates of not having "in_file.txt" in your current working directory, you can check with
import os
print os.getcwd()
this will show what files code can see
in_file = open(in_file, "r") # you must do the way so got an error
try this function:
def count_letters(in_file, out_file):
in_file_fd = open(in_file, "r") # open in file
out_file_fd = open(out_file, "w") # open out file
for line in in_file_fd:
for x in sorted(line):
count = line.count(x)
res = x + " " + str(count) + '\n'
print (res)
out_file_fd.write(res) # write the data into out file
in_file_fd.close() # close in_file
out_file_fd.close() # close out_file
count_letters('test.py', 'out_file')
It works for me, hope helpful.

How to interact with notepad document correctly in python?

I created a notepad text document called "connections.txt". I need to have some initial information inside it, several lines of just URLs. Each URL has it's own line. I put that in manually. Then in my program I have a function that checks if a URL is in the file:
def checkfile(string):
datafile = file(f)
for line in datafile:
if string in line:
return True
return False
where f is declared at the beginning of the program:
f = "D:\connections.txt"
Then I tried to write to the document like this:
file = open(f, "w")
if checkfile(user) == False:
usernames.append(user)
file.write("\n")
file.write(user)
file.close()
but it hasn't really been working correctly..I'm not sure what's wrong..am I doing it wrong?
I want the information in the notepad document to stay there ACROSS runs of the program. I want it to build up.
Thanks.
EDIT: I found something wrong... It needs to be file = f, not datafile = file(f)
But the problem is... It clears the text document every time I rerun the program.
f = "D:\connections.txt"
usernames = []
def checkfile(string):
file = f
for line in file:
if string in line:
return True
print "True"
return False
print "False"
file = open(f, "w")
user = "aasdf"
if checkfile(user) == False:
usernames.append(user)
file.write("\n")
file.write(user)
file.close()
I was working with the file command incorrectly...here is the code that works.
f = "D:\connections.txt"
usernames = []
def checkfile(string):
datafile = file(f)
for line in datafile:
if string in line:
print "True"
return True
print "False"
return False
user = "asdf"
if checkfile(user) == False:
usernames.append(user)
with open(f, "a") as myfile:
myfile.write("\n")
myfile.write(user)
The code that checks for a specific URL is ok!
If the problem is not erasing everything:
To write to the document without erasing everything you have to use the .seek() method:
file = open("D:\connections.txt", "w")
# The .seek() method sets the cursor to the wanted position
# seek(offset, [whence]) where:
# offset = 2 is relative to the end of file
# read more here: http://docs.python.org/2/library/stdtypes.html?highlight=seek#file.seek
file.seek(2)
file.write("*The URL you want to write*")
Implemented on your code will be something like:
def checkfile(URL):
# your own function as it is...
if checkfile(URL) == False:
file = open("D:\connections.txt", "w")
file.seek(2)
file.write(URL)
file.close()

Search for a string with in a module in a python file using Python

#!/usr/bin/env python`
import sys`
import binascii`
import string
sample = "foo.apples"
data_file = open("file1.py","r")
dat_file = open("file2.txt", "w")
for line in data_file:
if sample in line:
dat_file.writelines(line)
dat_file.close()`
When I do this I am able to find the string foo.apples. The problem is foo.apples is present in various lines in the python file. I want those lines which are inside a particular function. I need the lines within this def function.
Example:
def start():
foo.apples(a,b)
foo.apples(c,d) ... so on.
The following program finds defs and will append the sample string to the output file if the indentation remains within the def.
import re
sample = 'foo.apples'
data_file = open("file1.py", "r")
out_file = open("file2.txt", "w")
within_def = False
def_indent = 0
for line in data_file:
def_match = re.match(r'(\s*)def\s+start\s*\(', line) # EDIT: fixed regex
if def_match and not within_def:
within_def = True
def_indent = len(def_match.group(1))
elif within_def and re.match(r'\s{%s}\S' % def_indent, line):
within_def = False
if within_def and sample in line:
out_file.writelines(line)
out_file.close()
data_file.close()
Tested working on an example file1.py.
One, slightly off the beaten path approach to this would be to use the getsource method of the inspect module. Consider the following (theoretical) test1.py file:
class foo(object):
apples = 'granny_smith'
#classmethod
def new_apples(cls):
cls.apples = 'macintosh'
def start():
"""This is a pretty meaningless python function.
Attempts to run it will definitely result in an exception being thrown"""
print foo.apples
foo.apples = 3
[x for x in range(10)]
import bar as foo
Now you want to know about the start code:
import inspect
import test1 #assume it is somewhere that can be imported
print inspect.getsource(test1.start)
Ok, now we have only the source of that function. We can now parse through that:
for line in inspect.getsource(test1.start).splitlines():
if 'foo.apples' in line:
print line
There are some advantages here -- python does all the work of parsing out the function blocks when it imports the file. The downside though is that the file actually needs to be imported. Depending on where your files are coming from, this could introduce a HUGE security hole in your program -- You'll be running (potentially) "untrusted" code.
Here's a very non pythonic way, untested, but it should work.
sample = "foo.apples"
infile = open("file1.py", "r")
outfile = open("file2.txt", "w")
in_function = False
for line in infile.readlines():
if in_function:
if line[0] in(" ", "\t"):
if sample in line:
outfile.write(line)
else:
in_function = False
elif line.strip() == "def start():":
in_function = True
infile.close()
outfile.close()
I would suggest doing a function of this, which takes sample, the input file, and the function which we're supposed to search from as it's parameters. It would then return a list or tuple of all the lines that had the text in them.
def findFromFile(file, word, function):
in_function = False
matches = []
infile = open(file, "r")
for line in infile.readlines():
if in_function:
if line[0] in(" ", "\t"):
if word in line:
matches.append(line)
else:
in_function = False
elif line.strip() == "def %s():"%function:
in_function = True
infile.close()
return matches

Categories