python - mock open for reading data - python

E.g., I wrote some data to the file and then try to read them:
mocked_open = mock_open()
with patch('__builtin__.open', mocked_open, create=True):
with open('file', 'w') as f:
f.write('text')
with open('file', 'r') as f:
res = f.read()
But after this,res is empty. How to get written data for this file?

Related

Using if-else in "with" statement in Python

I want to open a file that may be gzipped or not. To open the file, I use either
with open(myfile, 'r') as f:
some_func(f) # arbitrary function
or
import gzip
with gzip.open(myfile, 'r') as f:
some_func(f)
I want to check if myfile has a gz extension or not, and then from there decide which with statement to use. Here's what I have:
# myfile_gzipped is a Boolean variable that tells me whether it's gzipped or not
if myfile_gzipped:
with gzip.open(myfile, 'rb') as f:
some_func(f)
else:
with open(myfile, 'r') as f:
some_func(f)
How should I go about it, without having to repeat some_func(f)?
if myfile_gzipped:
f = gzip.open(myfile, 'rb')
else:
f = open(myfile, 'r')
with f:
some_func(f)
The result of open and gzip.open is a context manager. with invokes the entry and exit methods on context managers. There is nothing special in calling those functions inside the with statement itself.
I find that ExitStacks can be helpful in these cases:
from contextlib import ExitStack
with ExitStack() as stack:
if myfile_gzipped:
f = stack.enter_context(gzip.open(myfile, 'rb'))
else:
f = stack.enter_context(open(myfile, 'r'))
some_func(f)
You can use the ternary operator to evaluate two different expressions based on a condition:
with gzip.open(myfile, 'rb') if myfile_gzipped else open(myfile, 'r') as f:
some_func(f)
You don't have to put open and with on the same line.
You can open the file as one step, and then do with f later.
if myfile_gzipped:
f = gzip.open(myfile, 'rb')
else:
f = open(myfile, 'r')
with f:
some_func(f)

How can I edit my code to print out the content of my created json file?

My program takes a csv file as input and writes it as an output file in json format. On the final line, I use the print command to output the contents of the json format file to the screen. However, it does not print out the json file contents and I don't understand why.
Here is my code that I have so far:
import csv
import json
def jsonformat(infile,outfile):
contents = {}
csvfile = open(infile, 'r')
reader = csvfile.read()
for m in reader:
key = m['No']
contents[key] = m
jsonfile = open(outfile, 'w')
jsonfile.write(json.dumps(contents))
csvfile.close()
jsonfile.close()
return jsonfile
infile = 'orders.csv'
outfile = 'orders.json'
output = jsonformat(infile,outfile)
print(output)
Your function returns the jsonfile variable, which is a file.
Try adding this:
jsonfile.close()
with open(outfile, 'r') as file:
return file.read()
Your function returns a file handle to the file jsonfile that you then print. Instead, return the contents that you wrote to that file. Since you opened the file in w mode, any previous contents are removed before writing the new contents, so the contents of your file are going to be whatever you just wrote to it.
In your function, do:
def jsonformat(infile,outfile):
...
# Instead of this:
# jsonfile.write(json.dumps(contents))
# do this:
json_contents = json.dumps(contents, indent=4) # indent=4 to pretty-print
jsonfile.write(json_contents)
...
return json_contents
Aside from that, you aren't reading the CSV file the correct way. If your file has a header, you can use csv.DictReader to read each row as a dictionary. Then, you'll be able to use for m in reader: key = m['No']. Change reader = csvfile.read() to reader = csv.DictReader(csvfile)
As of now, reader is a string that contains all the contents of your file. for m in reader makes m each character in this string, and you cannot access the "No" key on a character.
a_file = open("sample.json", "r")
a_json = json.load(a_file)
pretty_json = json.dumps(a_json, indent=4)
a_file.close()
print(pretty_json)
Using this sample to print the contents of your json file. Have a good day.

Pickle Dump Code Problem: content in .txt file

Here's my code:
list = ["example"]
def speichern(charts):
f = open("test.txt", "wb")
pickle.dump(list, f, )
f.close()
It works, but the content of test.txt is:
€]q ]q(X exampleqX qea
How do I fix this?

Python script that will go through folders and replace content in them [duplicate]

Currently I'm using this:
f = open(filename, 'r+')
text = f.read()
text = re.sub('foobar', 'bar', text)
f.seek(0)
f.write(text)
f.close()
But the problem is that the old file is larger than the new file. So I end up with a new file that has a part of the old file on the end of it.
If you don't want to close and reopen the file, to avoid race conditions, you could truncate it:
f = open(filename, 'r+')
text = f.read()
text = re.sub('foobar', 'bar', text)
f.seek(0)
f.write(text)
f.truncate()
f.close()
The functionality will likely also be cleaner and safer using open as a context manager, which will close the file handler, even if an error occurs!
with open(filename, 'r+') as f:
text = f.read()
text = re.sub('foobar', 'bar', text)
f.seek(0)
f.write(text)
f.truncate()
The fileinput module has an inplace mode for writing changes to the file you are processing without using temporary files etc. The module nicely encapsulates the common operation of looping over the lines in a list of files, via an object which transparently keeps track of the file name, line number etc if you should want to inspect them inside the loop.
from fileinput import FileInput
for line in FileInput("file", inplace=1):
line = line.replace("foobar", "bar")
print(line)
Probably it would be easier and neater to close the file after text = re.sub('foobar', 'bar', text), re-open it for writing (thus clearing old contents), and write your updated text to it.
I find it easier to remember to just read it and then write it.
For example:
with open('file') as f:
data = f.read()
with open('file', 'w') as f:
f.write('hello')
To anyone who wants to read and overwrite by line, refer to this answer.
https://stackoverflow.com/a/71285415/11442980
filename = input("Enter filename: ")
with open(filename, 'r+') as file:
lines = file.readlines()
file.seek(0)
for line in lines:
value = int(line)
file.write(str(value + 1))
file.truncate()
Honestly you can take a look at this class that I built which does basic file operations. The write method overwrites and append keeps old data.
class IO:
def read(self, filename):
toRead = open(filename, "rb")
out = toRead.read()
toRead.close()
return out
def write(self, filename, data):
toWrite = open(filename, "wb")
out = toWrite.write(data)
toWrite.close()
def append(self, filename, data):
append = self.read(filename)
self.write(filename, append+data)
Try writing it in a new file..
f = open(filename, 'r+')
f2= open(filename2,'a+')
text = f.read()
text = re.sub('foobar', 'bar', text)
f.seek(0)
f.close()
f2.write(text)
fw.close()

How do I write on a file after altering it with filehandle in python?

The purpose of this program is to backspace three times in a data file:
ofile = open(myfile, 'r')
file = open(myfile, 'r')
with open(myfile, 'rb+') as filehandle:
filehandle.seek(-3, os.SEEK_END)
filehandle.truncate()
I then attempted to add additional text after this by switching to the "write" function:
ofile = open(myfile, 'r')
file = open(myfile, 'r')
with open(myfile, 'rb+') as filehandle:
filehandle.seek(-3, os.SEEK_END)
filehandle.truncate()
ofile = open(myfile, 'w')
ofile.write('*')
This, however, overrides the entire data set and writes only "*" on a blank document. How do I add to the file without removing the rest of the content?
You need to use the append flag, instead of write. So, ofile = open(myfile, 'a')

Categories