Python read/write file without closing - python

Sometimes when I open a file for reading or writing in Python
f = open('workfile', 'r')
or
f = open('workfile', 'w')
I read/write the file, and then at the end I forget to do f.close(). Is there a way to automatically close after all the reading/writing is done, or after the code finishes processing?

with open('file.txt','r') as f:
#file is opened and accessible via f
pass
#file will be closed before here

You could always use the with...as statement
with open('workfile') as f:
"""Do something with file"""
or you could also use a try...finally block
f = open('workfile', 'r')
try:
"""Do something with file"""
finally:
f.close()
Although since you say that you forget to add f.close(), I guess the with...as statement will be the best for you and given it's simplicity, it's hard to see the reason for not using it!

Whatever you do with your file, after you read it in, this is how you should read and write it back:
$ python myscript.py sample.txt sample1.txt
Then the first argument (sample.txt) is our "oldfile" and the second argument (sample1.txt) is our "newfile". You can then do the following code into a file called "myscript.py"
from sys import argv
script_name,oldfile,newfile = argv
content = open(oldfile,"r").read()
# now, you can rearrange your content here
t = open(newfile,"w")
t.write(content)
t.close()

Related

Loop for opening .txt files

I have a list of .txt file in one folder, with names like: "image1.txt", "image2.txt", "image3.txt", etc.
I need to perform some operations for each file.
I was trying like this:
import glob
for each_file in glob.glob("C:\...\image\d+\.txt"):
print(each_file) (or whatever)
But it seems it doesn't work. How can I solve?
I think you are looking for something like this:
import os
for file in os.listdir('parent_folder'):
with open(os.path.join('parent_folder', file), 'r') as f:
data = f.read()
# operation on data
#Alternatively
for i in range(10):
with open(f'image{i}.txt', 'r') as f:
data = f.read()
# operation on data
The with operator takes care of everything to do with the file, so you don't need to worry about the file after it goes out of scope.
If you want to read and also write to the file in the same operation, use open(file, 'r+) and then the following:
with open(f'image{i}.txt', 'r+') as f:
data = f.read()
# operation on data
f.seek(0)
f.write(data)
f.truncate()
Take this answer, that I wrote.
path objects have the read_text method. As long as it can decode it, then it will read it - you shouldn't have a problem with text files. Also, since you are using windows paths, make sure to put an r before the string, like this r"C:\...\image\d+\.txt" or change the direction of the slashes. A quick example:
from pathlib import Path
for f in Path(r"C:\...\image\d+\").rglob('**/*.txt'):
print(f.read_text())

Reading a file without truncating it, creating it if it doesn't already exist

I want to read data from a file without truncating it.
I know I can use 'r' for reading.
But I also want to create the file if a FileNotFoundError is raised.
But using 'w', 'w+', 'a+' to create a file works, it also truncates any existing data in the file in later runs.
Basically looking for a replacement for:
try:
with open('filename', 'r') as file:
#if no error is raised, file already exits and
#can be read from: do stuff on file.
except FileNotFoundError:
with open('filename', 'x') as file:
pass
#no further actions are required here as the file
#is just being created
Answer at:
open file for random write without truncating?
states that I should open the file in 'rb+' mode, however 'rb+' raises a FileNotFoundError and does not create the file if it doesn't exist.
opening files in binary mode is also not suited for reading text files.
You could use os.path.exists() to replace the use of FileNotFoundError.
import os
path = '/tmp/test.info'
if os.path.exists(path):
with open(path, 'r') as infile:
print(infile.read())
else:
open(path, 'x')
You could also replace all of the os usage with pathlib if you're on Python 3.4+.
from pathlib import Path
path = Path('/tmp/test.info')
if path.is_file():
print(path.read_text())
else:
path.touch()
I'm not really sure whether either of these is much of an improvement, though. These could be reduced to one- or two-liners if it's brevity you want, but they'd be less readable, and still wouldn't be single commands.
You could try something like this:
>>> try:
... t = open('filename', 'r+')
... except FileNotFoundError:
... t = open('filename', 'x')
...
>>> with t as file:
... file.write("Testing:\n")
...
9
Assigning open() to a name and then using that name in a with statement also works
The best way I found of doing this is using:
file = open(file_name, 'a+')
file.seek(0)
a+ is a read/write mode that doesn't truncate the file, however, it starts reading at the end of the file; which is why seeking to the start of the file is needed afterwards.

How can I transfer data from one funtction to another?

I am trying to transfer data received from one function (reading) to another (writing).
Existing data inside file.txt should be transfer into json format and be printed to the console, that data should be taken and be written on the file called pfile.txt, by the second function.
I just can't get them to work together. When running each function separately as commands in plain shell, they work; combined, not so much. What am I missing here?
def reading():
filename = 'file.txt'
with open(filename, 'r') as f:
print(json.loads(f.read()))
reading()
def writing():
with open('pfile.txt', 'w+') as pf:
pf.write(reading() in writing()) <-- this doesn't work
pf.write('hello SO') <-- this does work
writing()
When you refer to a function with a pair of parenthesis, Python will call that function with no arguments and resolve it's return value (if any). This is not bash; functions pass data to each other as variables in memory, not through stdin/stdout.
Your code as written appears to be riddled with infinite loops (functions calling themselves) and likely will crash with "recursion depth exceeded" errors. These can be fixed by not calling functions within themselves (or having cycles of functions that call each other).
There's nothing about your code as written that needs multiple functions. I'd go down to 1 function:
def read_and_write():
filename = 'file.txt'
with open(filename, 'r') as f:
content = json.loads(f.read())
print(content)
with open('pfile.txt', 'w+') as pf:
pf.write(content)
If you want two functions, try the following:
def read():
filename = 'file.txt'
with open(filename, 'r') as f:
content = json.loads(f.read())
return content
def write():
content = read()
with open('pfile.txt', 'w+') as pf:
pf.write(content)

Write list of bytes into a file, but some records got lost

I am new to programming and got an issue with writing bytes. Here is what I wrote:
file = open('filePath/input.train', 'wb')
for i in range(len(myList)):
file.write(bytes((myList[i]),'UTF-8'));
If I print 'i' here, it is 629.
The '.train' suffix is required by the project. In order to check it, I read it and write to a txt file:
file = open('filePath/input.train', 'rb')
content = file.read()
testFile = open('filePath/test.txt', 'wb')
testFile.write(content)
Now, the problem is, len(list) = 629 while I got 591 lines in test.txt file. It brought me problems later.
Why did this happen and how should I solve it?
first, when you open and write a file, need remember close the file after the write.like this.
file = open('filePath/input.train', 'wb')
for i in range(len(myList)):
file.write(bytes((myList[i]),'UTF-8'));
file.close()
second, python code not must has ";"
third, file is python's keyword, so don't use file be your variable name. you can use f or my_file or anyone, but don't use python's keyword.
fourth, python has a iterator, use iterator is better than your for i in range(len(xxx)).
all of this, your code can look like this.
f = open('filePath/input.train', 'wb')
for line in myList:
f.write(bytes(line, 'UTF-8'))
f.close()

Print file passed in as argument

I have a very simple python script that should print the contents of a file that is passed like this: python script.py stuff.txt. I don't get any output.
Here is the code:
import sys
fname = sys.argv[1]
f = open(fname, 'r')
f.read()
From what I have read, this is supposed to work. Why not?
You read the file, but you don't do anything with the data.
print(f.read())
Or, for better style:
import sys
fname = sys.argv[1]
with open(fname, 'r') as f:
print(f.read())
This is the recommended way to use files. It guarantees the file is closed when you exit the with block. Does not really matter for your small script, but it's a good habit to take.

Categories

Resources