Checking for an entry in text file before adding - python

I have some fairly simple code i thought would work but it is not doing as it should, all i'm doing is reading a text file for a url, if it does not exist in the tex file we add it:
code:
def verify_links_working(self, url):
if url not in open("links/register.txt").read():
with open("links/register.txt", "a+") as file:
file.write("%s\n" % str(url).strip())
file.close()
It looks fairly straight forward but it still adds duplicate lines, is there something i have missed? any help is appreciated.

You can do both read and write on the same file, plus cleaning both url and urls from txt with strip. Since self is not used, I remove it by adding staticmethod(assuming you are using the function as a class function:
#staticmethod
def verify_links_working(url):
url_clean = url.strip()
with open('links/register.txt', 'r+') as file:
if url_clean not in {url.strip() for url in file}:
file.write(f'{url_clean}\n')
Even better, you can pass path to register.txt as an argument instead of hard coding it in your function. In that since your function will be more generic.

Related

How to insert data into a text file if the data doesn't exist already (Python)

I'm trying to create a webscraping script in Python where I follow a bunch of links and insert them into a .txt file. However, I want to do this only if the website already doesn't exist in the file.
I have written this code to insert the given website link into the file, so far (not working):
def writeSite(site):
file = open("websites.txt", 'a+')
# print(site)
if site in file.read():
return
file.write(site + "\n")
file.close()
Thanks in advance.
You were pretty close, but because you open the file to append to it, it starts with the file pointer at the end. You need to seek to the start to read its contents again:
def writeSite(site):
file = open("websites.txt", 'a+')
file.seek(0)
# print(site)
if site in file.read():
return
file.write(site + "\n")
file.close()
However, keep in mind that site in file.read() is very crude.
For example, imagine you already have 'http://somesite.com/page/' in the file but now you want to add 'http://somesite.com/' - the URL as a whole is not in the file, but your test will find it.
If you want to check whole lines (and be sure you deal with the file nicely), this would be better:
def writeSite(site):
site += '\n'
with open("websites.txt", 'a+') as f:
f.seek(0)
if site in f.readlines():
return
f.write(site)
It adds a newline to the name of the site to separate the URLs in the file and uses readlines to make use of that fact to check for the whole URL. Using with ensures the file always gets closed.
And since you want to read before writing anyway, you could use 'r+' as a mode, and skip the seek - but only if you can be sure the file already exists. I assume you chose 'a+' because that isn't the case.
(in case you worry that this changes the value of site - that's only true for the parameter inside the function. Whatever value you passed in outside the function will remain unaffected)

Download xml-file and save it to a text file

I'm very new at programming and have a problem. I need to create a Python function that uses the request external module to download an XML-file, and then saves the text of the response to a text file.
So far i've tried this:
import requests
def downloading_xml():
r = requests.get('https://www.w3schools.com/xml/simplexsl.xml')
print(r.text)
But I don't get it quite right. I think my main problem is the last part, I don't know how to save the text of the response to a text file. Any ideas? Thanks in advance!
Here you go. If you want to know more about Python file operations follow this link
Python I/O
import requests
def downloading_xml():
r = requests.get('https://www.w3schools.com/xml/simplexsl.xml')
print(r.text)
with open("filename.txt", "w+") as f:
f.write(r.text)
f.close()
Now call the function
downloading_xml()
To save to a text file you can do something like this:
textfile=open("anyname.xml",'w')
textfile.write(r.text)
textfile.close()
you may need to include the path to the file as well

Why wasn't my file opened?

I'm working on a project at the end of a book I read for Python, so in case this hasn't given it away for you, I'm still quite new to this.
I'm trying to use the open command to open a file that I know exists. I know that the code understands the file is there, because when I switch over to write mode, it clears my text file out, telling me that it can find the file but it just won't read it. Why is this happening? Here's the code-
openFile = open('C:\\Coding\\Projects\\Python\\One Day Project\\BODMAS\\userScores.txt', 'r')
def getUserPoint(userName):
for line in openFile:
split(',')
print(line, end = "")
I've tried a few variations where my openFile function is a local variable inside getUserPoint(), but that didn't make a difference either.
Editing because I missed a vital detail — the userScores.txt file is laid out as follows:
Annie, 125
The split() function is supposed to split the name and the score assigned to the name.
Your function isn't valid Python, as split isn't a globally defined function, but a built-in function of the type str. Try changing your function to something like this.
def getUserPoint(name):
for line in openFile:
line_split = line.split(",")
print(line_split, end = "")

Python and Flask - Trying to have a function return a file content

I am struggling to return a file content back to the user. Have a Flask code that receives a txt file from an user, then the Python function transform() is called in order to parse the infile, both codes are doing the job.
The issue is happening when I am trying to send (return) the new file (outfile) back to the user, the Flask code for that is also working OK.
But I don´t know how to have this Python transform function() "return" that file content, have tested several options already.
Following more details:
def transform(filename):
with open(os.path.join(app.config['UPLOAD_FOLDER'],filename), "r") as infile:
with open(os.path.join(app.config['UPLOAD_FOLDER'], 'file_parsed_1st.txt'), "w") as file_parsed_1st:
p = CiscoConfParse(infile)
'''
parsing the file uploaded by the user and
generating the result in a new file(file_parsed_1st.txt)
that is working OK
'''
with open (os.path.join(app.config['UPLOAD_FOLDER'], 'file_parsed_1st.txt'), "r") as file_parsed_2nd:
with open(os.path.join(app.config['UPLOAD_FOLDER'], 'file_parsed_2nd.txt'), "w") as outfile:
'''
file_parsed_1st.txt is a temp file, then it creates a new file (file_parsed_2nd.txt)
That part is also working OK, the new file (file_parsed_2nd.txt)
has the results I want after all the parsing;
Now I want this new file(file_parsed_2nd.txt) to "return" to the user
'''
#Editing -
#Here is where I was having a hard time, and that now is Working OK
#using the follwing line:
return send_file(os.path.join(app.config['UPLOAD_FOLDER'], 'file_parsed_2nd.txt'))
You do need to use the flask.send_file() callable to produce a proper response, but need to pass in a filename or a file object that isn't already closed or about to be closed. So passing in the full path would do:
return send_file(os.path.join(app.config['UPLOAD_FOLDER'], 'file_parsed_2nd.txt'))
When you pass in a file object you cannot use the with statement, as it'll close the file object the moment you return from your view; it'll only be actually read when the response object is processed as a WSGI response, outside of your view function.
You may want to pass in a attachment_filename parameter if you want to suggest a filename to the browser to save the file as; it'll also help determine the mimetype. You also may want to specify the mimetype explicitly, using the mimetype parameter.
You could also use the flask.send_from_directory() function; it does the same but takes a filename and a directory:
return send_from_directory(app.config['UPLOAD_FOLDER'], 'file_parsed_2nd.txt')
The same caveat about a mimetype applies; for .txt the default mimetype would be text/plain. The function essentially joins the directory and filename (with flask.safe_join() which applies additional safety checks to prevent breaking out of the directory using .. constructs) and passes that on to flask.send_file().

Write strings to another file

The Problem - Update:
I could get the script to print out but had a hard time trying to figure out a way to put the stdout into a file instead of on a screen. the below script worked on printing results to the screen. I posted the solution right after this code, scroll to the [ solution ] at the bottom.
First post:
I'm using Python 2.7.3. I am trying to extract the last words of a text file after the colon (:) and write them into another txt file. So far I am able to print the results on the screen and it works perfectly, but when I try to write the results to a new file it gives me str has no attribute write/writeline. Here it the code snippet:
# the txt file I'm trying to extract last words from and write strings into a file
#Hello:there:buddy
#How:areyou:doing
#I:amFine:thanks
#thats:good:I:guess
x = raw_input("Enter the full path + file name + file extension you wish to use: ")
def ripple(x):
with open(x) as file:
for line in file:
for word in line.split():
if ':' in word:
try:
print word.split(':')[-1]
except (IndexError):
pass
ripple(x)
The code above works perfectly when printing to the screen. However I have spent hours reading Python's documentation and can't seem to find a way to have the results written to a file. I know how to open a file and write to it with writeline, readline, etc, but it doesn't seem to work with strings.
Any suggestions on how to achieve this?
PS: I didn't add the code that caused the write error, because I figured this would be easier to look at.
End of First Post
The Solution - Update:
Managed to get python to extract and save it into another file with the code below.
The Code:
inputFile = open ('c:/folder/Thefile.txt', 'r')
outputFile = open ('c:/folder/ExtractedFile.txt', 'w')
tempStore = outputFile
for line in inputFile:
for word in line.split():
if ':' in word:
splitting = word.split(':')[-1]
tempStore.writelines(splitting +'\n')
print splitting
inputFile.close()
outputFile.close()
Update:
checkout droogans code over mine, it was more efficient.
Try this:
with open('workfile', 'w') as f:
f.write(word.split(':')[-1] + '\n')
If you really want to use the print method, you can:
from __future__ import print_function
print("hi there", file=f)
according to Correct way to write line to file in Python. You should add the __future__ import if you are using python 2, if you are using python 3 it's already there.
I think your question is good, and when you're done, you should head over to code review and get your code looked at for other things I've noticed:
# the txt file I'm trying to extract last words from and write strings into a file
#Hello:there:buddy
#How:areyou:doing
#I:amFine:thanks
#thats:good:I:guess
First off, thanks for putting example file contents at the top of your question.
x = raw_input("Enter the full path + file name + file extension you wish to use: ")
I don't think this part is neccessary. You can just create a better parameter for ripple than x. I think file_loc is a pretty standard one.
def ripple(x):
with open(x) as file:
With open, you are able to mark the operation happening to the file. I also like to name my file object according to its job. In other words, with open(file_loc, 'r') as r: reminds me that r.foo is going to be my file that is being read from.
for line in file:
for word in line.split():
if ':' in word:
First off, your for word in line.split() statement does nothing but put the "Hello:there:buddy" string into a list: ["Hello:there:buddy"]. A better idea would be to pass split an argument, which does more or less what you're trying to do here. For example, "Hello:there:buddy".split(":") would output ['Hello', 'there', 'buddy'], making your search for colons an accomplished task.
try:
print word.split(':')[-1]
except (IndexError):
pass
Another advantage is that you won't need to check for an IndexError, since you'll have, at least, an empty string, which when split, comes back as an empty string. In other words, it'll write nothing for that line.
ripple(x)
For ripple(x), you would instead call ripple('/home/user/sometext.txt').
So, try looking over this, and explore code review. There's a guy named Winston who does really awesome work with Python and self-described newbies. I always pick up new tricks from that guy.
Here is my take on it, re-written out:
import os #for renaming the output file
def ripple(file_loc='/typical/location/while/developing.txt'):
outfile = "output.".join(os.path.basename(file_loc).split('.'))
with open(outfile, 'w') as w:
lines = open(file_loc, 'r').readlines() #everything is one giant list
w.write('\n'.join([line.split(':')[-1] for line in lines]))
ripple()
Try breaking this down, line by line, and changing things around. It's pretty condensed, but once you pick up comprehensions and using lists, it'll be more natural to read code this way.
You are trying to call .write() on a string object.
You either got your arguments mixed up (you'll need to call fileobject.write(yourdata), not yourdata.write(fileobject)) or you accidentally re-used the same variable for both your open destination file object and storing a string.

Categories

Resources