I am creating a tempFile and then adding text to it by opening it with an editor(so that user can enter his message), and then save it to read the text from save NamedTemporaryFile.
with tempfile.NamedTemporaryFile(delete=False) as f:
f.close()
if subprocess.call([editor.split(" ")[0], f.name]) != 0:
raise IOError("{} exited with code {}.".format(editor.split(" ")[0], rc))
with open(f.name) as temp_file:
temp_file.seek(0)
for line in temp_file.readlines():
print line
But every time it is coming out to be blank. why is it so ?
If you are using SublimeText as the editor, you will need to pass in the -w or --wait argument to make sure that the Python program waits until you actually close SublimeText again.
Otherwise, you would just start to edit the file, and immediately try to read its contents which at that point are empty.
You could also verify that, by putting in a print before reading the file.
E.g.:
editor = ['/path/to/sublime_text', '-w']
with tempfile.NamedTemporaryFile(delete=False) as f:
f.close()
if subprocess.call(editor + [f.name]) != 0:
raise IOError()
# read file…
Here's a solution without editor interaction since I don't have enough information to mimic your editor setup.
import tempfile
with tempfile.NamedTemporaryFile(delete=False) as f:
f.close()
with open(f.name, f.mode) as fnew:
# Replace with editor interaction
fnew.write('test')
fnew.seek(0)
for line in fnew.readlines():
print line
At least on my system and version (2.7.2), I had to make these changes to allow the file object to be properly reopened and interacted with, and it builds correctly in Sublime. f.name is the temporary file path, and f.mode is the mode used by the already closed file (in this case it should default to 'w+b').
Related
I am trying to copy the content of one file to another.
The script successfully copies content to the file but when I try to run READ command with the output file to print the output, it is blank.
from sys import argv
script, inputFile, outputFile = argv
inFile = open(inputFile)
inData = inFile.read()
outFile = open(outputFile, 'w+')
outFile.write(inData)
print("The new data is:\n",outFile.read())
inFile.close()
outFile.close()
After the write operation the file pointer is at the end of file so you'd need to reset it to the start. Also, the filesystem IO buffers may not have been flushed at that point (you haven't closed the file yet)...
Simple solution: close the outFile and reopen it for reading.
As a side note: always make sure you DO close your files whatever happens, specially when writing, else you may end up with corrupted data. The simplest way is the with statement:
with open(...) as infile, (...) as outfile:
outfile.write(infile.read())
# at this point both files have been automagically closed
You forgot to return to the beginning of outFile after writing to it.
So inserting outFile.seek(0) should fix your issues.
After you are done writing, file pointer is at the end of the file, so no data is there. Reposition pointer to start of the file.
Started Python a week ago and I have some questions to ask about reading and writing to the same files. I've gone through some tutorials online but I am still confused about it. I can understand simple read and write files.
openFile = open("filepath", "r")
readFile = openFile.read()
print readFile
openFile = open("filepath", "a")
appendFile = openFile.write("\nTest 123")
openFile.close()
But, if I try the following I get a bunch of unknown text in the text file I am writing to. Can anyone explain why I am getting such errors and why I cannot use the same openFile object the way shown below.
# I get an error when I use the codes below:
openFile = open("filepath", "r+")
writeFile = openFile.write("Test abc")
readFile = openFile.read()
print readFile
openFile.close()
I will try to clarify my problems. In the example above, openFile is the object used to open file. I have no problems if I want write to it the first time. If I want to use the same openFile to read files or append something to it. It doesn't happen or an error is given. I have to declare the same/different open file object before I can perform another read/write action to the same file.
#I have no problems if I do this:
openFile = open("filepath", "r+")
writeFile = openFile.write("Test abc")
openFile2 = open("filepath", "r+")
readFile = openFile2.read()
print readFile
openFile.close()
I will be grateful if anyone can tell me what I did wrong here or is it just a Pythong thing. I am using Python 2.7. Thanks!
Updated Response:
This seems like a bug specific to Windows - http://bugs.python.org/issue1521491.
Quoting from the workaround explained at http://mail.python.org/pipermail/python-bugs-list/2005-August/029886.html
the effect of mixing reads with writes on a file open for update is
entirely undefined unless a file-positioning operation occurs between
them (for example, a seek()). I can't guess what
you expect to happen, but seems most likely that what you
intend could be obtained reliably by inserting
fp.seek(fp.tell())
between read() and your write().
My original response demonstrates how reading/writing on the same file opened for appending works. It is apparently not true if you are using Windows.
Original Response:
In 'r+' mode, using write method will write the string object to the file based on where the pointer is. In your case, it will append the string "Test abc" to the start of the file. See an example below:
>>> f=open("a","r+")
>>> f.read()
'Test abc\nfasdfafasdfa\nsdfgsd\n'
>>> f.write("foooooooooooooo")
>>> f.close()
>>> f=open("a","r+")
>>> f.read()
'Test abc\nfasdfafasdfa\nsdfgsd\nfoooooooooooooo'
The string "foooooooooooooo" got appended at the end of the file since the pointer was already at the end of the file.
Are you on a system that differentiates between binary and text files? You might want to use 'rb+' as a mode in that case.
Append 'b' to the mode to open the file in binary mode, on systems
that differentiate between binary and text files; on systems that
don’t have this distinction, adding the 'b' has no effect.
http://docs.python.org/2/library/functions.html#open
Every open file has an implicit pointer which indicates where data will be read and written. Normally this defaults to the start of the file, but if you use a mode of a (append) then it defaults to the end of the file. It's also worth noting that the w mode will truncate your file (i.e. delete all the contents) even if you add + to the mode.
Whenever you read or write N characters, the read/write pointer will move forward that amount within the file. I find it helps to think of this like an old cassette tape, if you remember those. So, if you executed the following code:
fd = open("testfile.txt", "w+")
fd.write("This is a test file.\n")
fd.close()
fd = open("testfile.txt", "r+")
print fd.read(4)
fd.write(" IS")
fd.close()
... It should end up printing This and then leaving the file content as This IS a test file.. This is because the initial read(4) returns the first 4 characters of the file, because the pointer is at the start of the file. It leaves the pointer at the space character just after This, so the following write(" IS") overwrites the next three characters with a space (the same as is already there) followed by IS, replacing the existing is.
You can use the seek() method of the file to jump to a specific point. After the example above, if you executed the following:
fd = open("testfile.txt", "r+")
fd.seek(10)
fd.write("TEST")
fd.close()
... Then you'll find that the file now contains This IS a TEST file..
All this applies on Unix systems, and you can test those examples to make sure. However, I've had problems mixing read() and write() on Windows systems. For example, when I execute that first example on my Windows machine then it correctly prints This, but when I check the file afterwards the write() has been completely ignored. However, the second example (using seek()) seems to work fine on Windows.
In summary, if you want to read/write from the middle of a file in Windows I'd suggest always using an explicit seek() instead of relying on the position of the read/write pointer. If you're doing only reads or only writes then it's pretty safe.
One final point - if you're specifying paths on Windows as literal strings, remember to escape your backslashes:
fd = open("C:\\Users\\johndoe\\Desktop\\testfile.txt", "r+")
Or you can use raw strings by putting an r at the start:
fd = open(r"C:\Users\johndoe\Desktop\testfile.txt", "r+")
Or the most portable option is to use os.path.join():
fd = open(os.path.join("C:\\", "Users", "johndoe", "Desktop", "testfile.txt"), "r+")
You can find more information about file IO in the official Python docs.
Reading and Writing happens where the current file pointer is and it advances with each read/write.
In your particular case, writing to the openFile, causes the file-pointer to point to the end of file. Trying to read from the end would result EOF.
You need to reset the file pointer, to point to the beginning of the file before through seek(0) before reading from it
You can read, modify and save to the same file in python but you have actually to replace the whole content in file, and to call before updating file content:
# set the pointer to the beginning of the file in order to rewrite the content
edit_file.seek(0)
I needed a function to go through all subdirectories of folder and edit content of the files based on some criteria, if it helps:
new_file_content = ""
for directories, subdirectories, files in os.walk(folder_path):
for file_name in files:
file_path = os.path.join(directories, file_name)
# open file for reading and writing
with io.open(file_path, "r+", encoding="utf-8") as edit_file:
for current_line in edit_file:
if condition in current_line:
# update current line
current_line = current_line.replace('john', 'jack')
new_file_content += current_line
# set the pointer to the beginning of the file in order to rewrite the content
edit_file.seek(0)
# delete actual file content
edit_file.truncate()
# rewrite updated file content
edit_file.write(new_file_content)
# empties new content in order to set for next iteration
new_file_content = ""
edit_file.close()
While doing some Python tutorials, the author of the book asked for the following (opening a file and reading its content):
#we could do this in one line, how?
in_file = open(from_file)
indata = in_file.read()
How can I do this in one line?
You can get all the contents of the file from a file handler by by simply extending what you have with your path and reading from it.
indata = open(from_file).read()
However, it's more obvious what's happening and easier to extend if you use a with block.
with open(from_file) as fh: # start a file handler that will close itself!
indata = fh.read() # get all of the contents of in_file in one go as a string
Beyond that, you should protect your file opening and closing from IOErrors if (for example) your file path does not exist.
Finally, files are by default opened read-only and raise an error if you (or someone else later) attempts to write to it, which will safeguard data blocks. You can change this from 'r' to a variety of other options depending on your needs.
Here is a fairly complete example with the above concepts.
def get_file_contents(input_path):
try:
with open(input_path, 'r') as fh:
return fh.read().strip()
except IOError:
return None
I am writing a script to log into a switch, write the config to a file, and then rename the file. I have the parts working separately. The issue is that I cannot figure out how to get all parts with in the same function so that I can use the function on a list of devices. I get a file not open for reading in the for 'line in f' statement. when as far as i can see the file is still open.
I have tried writing a function to rename the file that works on its own, but not when in this script with the other parts.
I have another script that i wrote that has the rename portion outside of the function which works, but will not work to rename the file if multiple hosts are called with the Exscript 'quickstart' module.
Thanks for any help,
from Exscript.util.start import quickstart
import os
import datetime
import time
time = datetime.datetime.now().strftime("%d-%m-%Y")
tm = 'c:/test/tmp.txt'
def do_something(job, host, conn):
f = open(tm, 'w+') #opens File with read and write permissions
conn.execute('term len 0')
conn.execute('sh run')
f.write(conn.response)
conn.execute('quit')
#this is the part where the error comes
for line in f:
if "hostname" in line:
host = line.strip()
test = 'c:/test/' + host[9:] + 'on' + time + '.txt'
os.rename(tm, test)
quickstart('ssh://x.x.x.x', do_something)
According to the manual, mode w+ truncates (removes all the content from) the file. If you want to open the file for both reading and writing without destroying its contents, use mode r+ or a+.
::edit:: Note, I'm not sure how this works on Windows.
You have to test the file pointer at the beginning of the file using f.seek(0). Or first write to the file then close it then reopen it for reading. But you dont need a file at all - you can as well work on a local variable.
is there a way to open files without using QFileDialog.getOpenFileName parameter? The thing is, I have a some buttons that upon clicking them, a notepad will pop up in which you can type anything into the notepad. Then, you can save whatever you wrote in that notepad as a text file. What I want to do is, if I click the button again, I will reopen the file that I had previously edited via the notepad and can continue typing where I left off. However, I don't want to use getOpenFileName. Would it be possible to open a file without using this functionality? Below is my attempt but my if statement keeps evaluating to be false. If anyone could help that would be great. Thanks!
#Testing if the file already exists
if(os.path.exists("~/Desktop/" +self.fileName + ".txt")):
f = open(self.fileName + ".txt", 'r')
filedata = f.read()
self.text.setText(filedata)
f.close()
#Opens a new notepad if there wasn't a previous fileconstructed
else:
self.textBox = textBoxWindow(self.fileName)
self.textBox.show()
If you are on Winsows (you said the word Notepad), you can use the subprocess module to open any file with whatever program currently associated with the file type as follows:
import subprocess
self.filename = r'C:\test.txt'
subprocess.call(['start', self.filename], shell=True)
But the shell=True argument is kinda dangerous, especially of the filename comes as an input.
you can use the webbrowser module too, though not supported use of it I guess:
import webbrowser
webbrowser.open(self.filename)