Python script creating unexpected blank rows in csv (using bottle, csv, os) - python

Initial users.csv file- columns are respectively username,real name,password.
fraud,mike ross,iloveharveynew
abc,ab isss c,coolgal
xyz,name last,rockpassnew
Algorithm-
1. Input username (from a cookie) & new-password from a html form.
2. Iterate over the csv file to print all the rows that do not contain 'username' to a new file final.csv
3. Remove users.csv file.
4. Append username,real name,new password to final.csv file.
5. Rename final.csv to users.csv
For instance, let's say user xyz was logged in and username=xyz was retrieved from cookie. The user changed the password to rockpassnewnew.
Output users.csv file-
fraud,mike ross,iloveharveynew
abc,ab isss c,coolgal
xyz,name last,rockpassnewnew
Here is the functioned defined that does this which is called from a controller-
def change(self, new_password):
errors = []
if len(new_password) < 3: errors.append('new password too short')
if errors:
return errors
else:
with open('users.csv','r') as u:
users = csv.reader(u)
with open('final.csv', 'a') as f:
final=csv.writer(f)
for line in users:
variableforchecking1 = bottle.request.get_cookie('username')
if variableforchecking1 not in line:
final.writerow(line)
os.remove('users.csv')
variableforchecking1 = bottle.request.get_cookie('username')
variableforchecking2 = bottle.request.get_cookie('real_name')
with open('final.csv', 'a') as f:
final=csv.writer(f)
final.writerow([variableforchecking1, variableforchecking2, new_password])
os.rename ('final.csv','users.csv')
return []
The controller code which calls this function is-
#bottle.get('/change')
def change():
return bottle.template('change')
#bottle.post('/change')
def changePost():
new_password = bottle.request.forms.get('new-password')
username = me.username()
errors = me.change(new_password)
if errors:
return bottle.template('change', errors=errors)
me.login(username, new_password)
return bottle.redirect('/home')
How to prevent these blank rows from being created because every time a password is changed, the number of blank rows increase considerably?

When opening a CSV file to be written to using a csv.writer, take care how you open the file.
The problem is that csv.writer does its own handling of line-endings. If a file opened with open is not opened carefully, the file object will also replace LF line-endings with CR+LF when writing data. So when both are making these changes, the line endings in the output file can become CR+CR+LF. Text editors will often interpret this as two line endings.
The fix is to open the file in binary mode in Python 2, or with newline='' in Python 3 as recommended by the documentation for the csv module. To do this, replace both occurrences of
with open('final.csv', 'a') as f:
with
with open('final.csv', 'ab') as f:
if you are using Python 2, or
with open('final.csv', 'a', newline='') as f:
if you are using Python 3.

Related

Loop Not Functioning well

Guys i'v got a little problem with my code. The code is supposed to check a list of numbers and group them in a text file provider based but doesn't work as expected. It only saved a single number in a file for each provider instead of multiple ones. This is my code , if anyone could help i'd be grateful.Sorry if my code is too traditional
def main():
dead = open('invalid_no.txt', 'a+')
print('-------------------------------------------------------')
print('-------------------------------------------------------')
list = input('Your Phone Numbers List : ')
base_url = "http://apilayer.net/api/validate"
params = {
'access_key': '3246123d1d67e385b1d9fa11d0e84959',
'number': '',
}
numero = open(list, 'r')
for num in numero:
num = num.strip()
if num:
lines = num.split(':')
params['number'] = lines[0]
response = requests.get(base_url, params=params)
print('status:', response.status_code)
print('-------------------------------------')
try:
resp = response.json()
print('number:', resp['valid'])
print('number:', resp['international_format'])
print('country:', resp['country_name'])
print('location:',resp['carrier'])
print('-------------------------------------')
mok = open(resp['carrier'],'w+')
if resp['carrier'] == mok.name:
mok.write(num +'\n')
except FileNotFoundError:
if resp['carrier'] == '':
print('skipping')
else:
mok = open(resp['carrier'],'w+')
if resp['carrier'] == mok.name:
mok.write(num)
else:
print('No')
if __name__ == '__main__': main()
Opening a file with mode "w" will erase the existing file and start with an empty new one. That is why you are getting only one number. Every time you write to the file, you overwrite whatever was there before. There is no mode "w+". I believe that ought to cause a ValueError: invalid mode: 'w+', but in fact it seems to do the same as "w". The fact that "r+" exists doesn't mean you can infer that there is also an undocumented "w+".
From the documentation for open():
The second argument is another string containing a few characters
describing the way in which the file will be used. mode can be 'r'
when the file will only be read, 'w' for only writing (an existing
file with the same name will be erased), and 'a' opens the file for
appending; any data written to the file is automatically added to the
end. 'r+' opens the file for both reading and writing. The mode
argument is optional; 'r' will be assumed if it’s omitted.
So, no "w+".
I think you want mode "a" for append. But if you do that, the first time your code tries to write to the file, it won't be there to append to, so you get the file not found error that you had a problem with.
Before writing to the file, check to see if it is there. If not, open it for writing, otherwise open it for appending.
if os.path.exists(resp['carrier']):
mok = open(resp['carrier'],'a')
else:
mok = open(resp['carrier'],'w')
or, if you have a taste for one-liners,
mok = open(resp['carrier'],'a' if os.path.exists(resp['carrier']) else 'w')
Also your code never calls close() on the file after it is finished writing to it. It should. Forgetting it can result in missing data or other baffling behaviour.
The best way not to forget it is to use a context manager:
with open(resp['carrier'],'a' if os.path.exists(resp['carrier']) else 'w') as mok:
# writes within the with-block here
# rest of program here
# after the with-block ends, the context manager closes the file for you.

How to make a program that replaces newlines in python file with a string [duplicate]

This question already has answers here:
Why doesn't calling a string method (such as .replace or .strip) modify (mutate) the string?
(3 answers)
Closed 3 years ago.
I am trying to display my python file in html and therefore I would like to replace every time the file jumps to a newline with < br> but the program I've written is not working.
I've looked on here and tried changing the code around a bit I have gotten different results but not the ones I need.
with open(path, "r+") as file:
contents = file.read()
contents.replace("\n", "<br>")
print(contents)
file.close()
I want to have the file display < br> every time I have a new line but instead the code dosen't change anything to the file.
Here is an example program that works:
path = "example"
contents = ""
with open(path, "r") as file:
contents = file.read()
new_contents = contents.replace("\n", "<br>")
with open(path, "w") as file:
file.write(new_contents)
Your program doesn't work because the replace method does not modify the original string; it returns a new string.
Also, you need to write the new string to the file; python won't do it automatically.
Hope this helps :)
P.S. a with statement automatically closes the file stream.
Your code reads from the file, saves the contents to a variable and replaces the newlines. But the result is not saved anywhere. And to write the result into a file you must open the file for writing.
with open(path, "r+") as file:
contents = file.read()
contents = contents.replace("\n", "<br>")
with open(path, "w+") as file:
contents = file.write(contents)
there are some issues in this code snippet.
contents.replace("\n", "<br>") will return a new object which replaced \n with <br>, so you can use html_contents = contents.replace("\n", "<br>") and print(html_contents)
when you use with the file descriptor will close after leave the indented block.
Try this:
import re
with open(path, "r") as f:
contents = f.read()
contents = re.sub("\n", "<br>", contents)
print(contents)
Borrowed from this post:
import tempfile
def modify_file(filename):
#Create temporary file read/write
t = tempfile.NamedTemporaryFile(mode="r+")
#Open input file read-only
i = open(filename, 'r')
#Copy input file to temporary file, modifying as we go
for line in i:
t.write(line.rstrip()+"\n")
i.close() #Close input file
t.seek(0) #Rewind temporary file to beginning
o = open(filename, "w") #Reopen input file writable
#Overwriting original file with temporary file contents
for line in t:
o.write(line)
t.close() #Close temporary file, will cause it to be deleted

Strange Addition At The End Of .txt File Following fout.write() - Python

I am writing a program that will pull variables from a template and effectively Find/Replace into a template.
Example Template:
VARIABLES
#username
#password
#secret
###########################################################
My username is #username
Password is #password
Secret is #secret
The program will find each variable and ask one by one for user input, opening the file, saving the contents and then closing the file ready for the next variable.
All is working well besides a strange one. Once I have run the code, the end of my text file appears to go a little wild. See below output. As you can see it successfully took the variables and placed them, however it added "is TESTis TESTetis #secret" to the end?
VARIABLES
User
Pass
TEST
###########################################################
My username is User
Password is Pass
Secret is TESTis TESTis TESTetis #secret
I am new to Python (this week) so excuse the code below. I have made it work in my own special way! It may not be the most efficient. Just struggling to see where the extra is being added.
Code:
##COPY CONTENTS FROM READ ONLY TO NEW FILE
with open("TestTemplate.txt", "rt") as fin:
with open("out.txt", "wt") as fout:
for line in fin:
fout.write(line)
fin.seek(0)
fout.seek(0)
fin.close()
fout.close()
##PULL VARIABLES AND FIND/REPLACE CONTENTS
with open("out.txt", "rt") as fin:
with open("out.txt", "rt") as searchf:
with open("out.txt", "r+") as fout:
for line in fin:
if line.startswith("#"):
trimmedLine = line.rstrip()
## USER ENTRY
entry = input("Please Enter " + trimmedLine + ": ")
for line in searchf:
## ENSURE ONLY VARIABLES AFTER '#' ARE EDITED. KEEPS IT NEAT
if trimmedLine in line:
fout.write(line.replace(trimmedLine,entry))
else:
fout.write(line)
##RESET FOCUS TO THE TOP OF THE FILE READY FOR NEXT ITERATION
searchf.seek(0)
fout.seek(0)
Thanks in advance
Your replacement strings are shorter than the original template place holders, resulting in leftover characters after you perform file seek. You should truncate the file before you call seek() so that the extra character at the end can be trimmed.
##RESET FOCUS TO THE TOP OF THE FILE READY FOR NEXT ITERATION
searchf.seek(0)
fout.truncate()
fout.seek(0)
You are opening the same file (out.txt) in different modes at the same time - doesn't this strike you as evil? It is like having 3 people cooking in the same pan. One does eggs, one bacon, the third caramel: might work out - wouldnt like to taste it.
Cleaner code IPO-Model (yeah its old, but still valid):
Open file, read in content, close file.
Do your replacements.
Open output file, write replaced text, close file.
Shorter version of reading files:
with open("TestTemplate.txt", "rt") as fin,
open("out.txt", "wt") as fout:
text = fin.read() # read in text from template
fout.write(text) # you could simply use module os and copy() the file ...
# or simply skip copying here and use open("out.txt","w") below
Using a fixed text here - you could aquire it as above:
text = """VARIABLES
#username
#password
#secret
###########################################################
My username is #username
Password is #password
Secret is #secret"""
replaceMe = {} # dictionary to hold the to be replaced parts and its replacement
# go through all lines
for l in text.splitlines():
if l.startswith("#"): # if it starts with #, ask for content top replace it with
replaceMe[l.rstrip()] = input("Please Enter {}:".format(l.rstrip()))
newtext = text
# loop over all keys in dict, replace key in text
for k in replaceMe:
newtext = newtext.replace(k,replaceMe[k])
print(text)
print(newtext)
# save changes - using "w" so you can skip copying the file further up
with open("out.txt","w") as f:
f.write(text)
Output after replacement:
VARIABLES
a
b
c
###########################################################
My username is a
Password is b
Secret is c

Checking file if exist then append record

I am creating a log file with line by line records.
1- If file does not exist, it should create file and append header row and the record
2- if it exists, check the text timeStamp in first line. If it exist then append the record otherwise add header columns and record itself
I tried both w,a and r+; nothing worked for me. Below is my code:
logFile = open('Dump.log', 'r+')
datalogFile = log.readline()
if 'Timestamp' in datalogFile:
logFile.write('%s\t%s\t%s\t%s\t\n'%(timestamp,logread,logwrite,log_skipped_noweight))
logFile.flush()
else:
logFile.write('Timestamp\t#Read\t#Write\t#e\n')
logFile.flush()
logFile.write('%s\t%s\t%s\t%s\t\n'%(timestamp,logread,logwrite,log_skipped))
logFile.flush()
Code fails if file don't exist
Use 'a+' mode:
logFile = open('Dump.log', 'a+')
description:
a+
Open for reading and writing. The file is created if it does not
exist. The stream is positioned at the end of the file. Subsequent
writes to the file will always end up at the then current
end of file, irrespective of any intervening fseek(3) or similar
Following code would work:
import os
f = open('myfile', 'ab+') #you can use a+ if it's not binary
f.seek(0, os.SEEK_SET)
print f.readline() #print the first line
f.close()
Try this:
import os
if os.path.exists(my_file):
print 'file does not exist'
# some processing
else:
print 'file exists'
# some processing
You're opening the file in r+ mode which means you assume the file exists. Also, if you intend the write on the file, you should open it with a+ mode (unashamedly stealing ndpu's explanation)
Your code would become:
logFileDetails = []
with open("Dump.log","a+") as logFile:
logFileDetails = logFile.readLines()
if logFileDetails and "Timestamp" in logFileDetails:
pass # File exists, write your stuff here
else:
pass # Log file doesn't exist, write timestamp here
Checking a file existence introduces a race condition, i.e. another process can create it or delete it after the check returns false or true, respectively, creating heavy bugs. You should instead use:
if open('path\to.filename', 'a+') != '':
stuff_if_exists
else:
stuff_if_not_exists

How to check if an data already present in a CSV file using Python

Good day all,
I am trying to write a python script that picks up IP address(es) from a textfile, check if the IP addresses already present in CSV file, if IP address is already present then do nothing (pass), if the IP is not present in the CSV file then append the IP address in the CSV file.
I can add the IP addresses to the CSV file but I am not able to get my head around with how to check if the IP address is already present in the file.
if os.path.isfile('IP_file.txt'):
logfile = open('IP_file.txt', 'r')
csv_file = open('csv_file.csv', 'ab')
for line in logfile:
if line in csv_file: # This is not working
pass
else:
csv_file.write(line)
csv_file.close()
logfile.close()
else:
print('No file with filename ' logfile 'created')
I also tried to use the CSV module but no luck. Any help is much appreciated.
CSV is just a text format. Read it line by line, test every line against your IP. Like
ip="192.168.1.1"
for line in csv_file:
if ip in line:
found = True
break
I am a bit concerned against your cycling over file on the disk. Probably it is better to read files into memories (find all IPs in CSV file first and put in a list) and then check against the list instead of opening and iterating over whole CSV file for every line of IP file.
Keep a list or dict that holds the unique fetched values:
found_address = []
with open('IP_file.txt', 'r') as logfile:
with open('csv_file.csv', 'ab') as csv_file:
for line in logfile:
if not line in found_address:
csv_file.write(line)
found_address.append(line)
You are opening csv_file.csv in append mode ab. And then you are trying to check line in csv_file. In append-mode file-pointer points to the end-of-file.
little crazy functional-style python:
ip_file = set(map(str.strip, open('IP_file.txt').readlines()))
if CSV file is: 192.168.1.1,192.168.1.2,192.168.1.3,...
csv_file = set(map(str.strip, open('csv_file.csv').read().split(',')))
diff_ip = ip_file - csv_file
open('csv_file.csv','a').write(''.join(map(lambda x: ',{}'.format(x), list(diff_ip))))

Categories