Write string and date to text file in Python 3 - python

Trying to figure out how to out a guessing game score plus the date & time to a text file with a new line each time, keeping the old text.
This is what I've got so far;
print('You scored %s.' % scr)
file = open("scr.txt", mode='w')
file.write('Printed string %s.\n' % scr)
This isn't working by the way - it's showing that an edit has been made to the text file but nothing is showing up in the text file - so I'm doing something wrong.
I want the text file to read 'Printed string scr recorded at date & time. As well as wanting a new line each time upon writing and keeping what has been written before.
Thanks in advance. Any help would be greatly appreciated.

You're not calling file.close() anywhere. Until you do that (or file.flush()), there is no guarantee that anything will be written to the file; it could all be sitting around in a buffer somewhere.
A better way to do this is to use a with statement, so you don't have to remember to call close.
This is explained indirectly by Reading and Writing Files in the tutorial. The reference documentation explaining it in detail is scattered around the io docs, which can be hard for a novice to understand.
Also, opening the file in 'w' mode will replace the entire file each time. You want to append to the existing file, which means you need 'a' mode. See the tutorial section Reading and Writing Files or the open documentation for more details.
Adding a new line, you've already got right, with the \n in the format string.
Finally, you can get the date and time with the datetime module. If you don't mind the default ISO date format, you can just format the datetime object as a string.
Putting it all together:
import datetime
with open("scr.txt", mode='a') as file:
file.write('Printed string %s recorded at %s.\n' %
(scr, datetime.datetime.now()))

Is this what you want?
from datetime import datetime
with open('scr.txt', 'a') as file:
file.write('Printed string %s. Recorded at: %s\n' % scr %datetime.now())
Demo:
>>> n = datetime.now()
>>> print("%s"%n)
2013-12-11 08:16:38.029267

I think what you're missing is a flush and close. Python (like many other languages) uses buffers to manage data writes and batch writes to be more efficient. Try adding this after to see if you actually get some output in your file.
file.close()
Additionally, to keep the previous data in your file, you'll want to open in append mode.
file = open("scr.txt", "a")
This way, writes will append to the end of the file instead of truncating and rewriting your scores.

Related

The python command-line file handling doesn't work? am i working correctly?

I am a new python learner and now i have entered into file handling.
I tried solution for my problem but failed, so posting my question. before duplication please consider my question.
I tried to create a file, it worked.
writing in the file also worked.
But when i tried to read the text or values in the file, it returns empty.
I use command line terminal to work with python and running in Ubuntu OS.
The coding which I have tried is given below. The file is created in the desired location and the written text is also present.
f0=open("filehandling.txt","wb")
f0.write("my second attempt")
s=f0.read(10);
print s
I also tried with wb+, r+. But it just returns as empty
edit 1:
I have attached the coding below. I entered one by one in command line
fo = open("samp.txt", "wb")
fo.write( "Text is here\n");
fo.close()
fo = open("samp.txt", "r+")
str = fo.read(10);
print "Read String is : ", str
fo.close()
First of all if you open with wb flag then the file will be only in writeable mode. If you want to both read and write then you need wb+ flag. If you don't want the file to be truncated each time then you need rb+.
Now files are streams with pointers pointing at a certain location inside the file. If you write
f0.write("my second attempt")
then the pointer points at the [pointer before writing] (in your case the begining of the file, i.e. 0) plus [length of written bytes] (in your case 17, which is the end of the file). In order to read whole file you have to move that pointer back to the begining and then read:
f0.seek(0)
data = f0.read()

writing output for python not functioning

I am attempting to output a new txt file but it come up blank. I am doing this
my_file = open("something.txt","w")
#and then
my_file.write("hello")
Right after this line it just says 5 and then no text comes up in the file
What am I doing wrong?
You must close the file before the write is flushed. If I open an interpreter and then enter:
my_file = open('something.txt', 'w')
my_file.write('hello')
and then open the file in a text program, there is no text.
If I then issue:
my_file.close()
Voila! Text!
If you just want to flush once and keep writing, you can do that too:
my_file.flush()
my_file.write('\nhello again') # file still says 'hello'
my_file.flush() # now it says 'hello again' on the next line
By the way, if you happen to read the beautiful, wonderful documentation for file.write, which is only 2 lines long, you would have your answer (emphasis mine):
Write a string to the file. There is no return value. Due to buffering, the string may not actually show up in the file until the flush() or close() method is called.
If you don't want to care about closing file, use with:
with open("something.txt","w") as f:
f.write('hello')
Then python will take care of closing the file for you automatically.
As Two-Bit Alchemist pointed out, the file has to be closed. The python file writer uses a buffer (BufferedIOBase I think), meaning it collects a certain number of bytes before writing them to disk in bulk. This is done to save overhead when a lot of write operations are performed on a single file.
Also: When working with files, try using a with-environment to make sure your file is closed after you are done writing/reading:
with open("somefile.txt", "w") as myfile:
myfile.write("42")
# when you reach this point, i.e. leave the with-environment,
# the file is closed automatically.
The python file writer uses a buffer (BufferedIOBase I think), meaning
it collects a certain number of bytes before writing them to disk in
bulk. This is done to save overhead when a lot of write operations are
performed on a single file. Ref #m00am
Your code is also okk. Just add a statement for close file, then work correctly.
my_file = open("fin.txt","w")
#and then
my_file.write("hello")
my_file.close()

Python conditional statement based on text file string

Noob question here. I'm scheduling a cron job for a Python script for every 2 hours, but I want the script to stop running after 48 hours, which is not a feature of cron. To work around this, I'm recording the number of executions at the end of the script in a text file using a tally mark x and opening the text file at the beginning of the script to only run if the count is less than n.
However, my script seems to always run regardless of the conditions. Here's an example of what I've tried:
with open("curl-output.txt", "a+") as myfile:
data = myfile.read()
finalrun = "xxxxx"
if data != finalrun:
[CURL CODE]
with open("curl-output.txt", "a") as text_file:
text_file.write("x")
text_file.close()
I think I'm missing something simple here. Please advise if there is a better way of achieving this. Thanks in advance.
The problem with your original code is that you're opening the file in a+ mode, which seems to set the seek position to the end of the file (try print(data) right after you read the file). If you use r instead, it works. (I'm not sure that's how it's supposed to be. This answer states it should write at the end, but read from the beginning. The documentation isn't terribly clear).
Some suggestions: Instead of comparing against the "xxxxx" string, you could just check the length of the data (if len(data) < 5). Or alternatively, as was suggested, use pickle to store a number, which might look like this:
import pickle
try:
with open("curl-output.txt", "rb") as myfile:
num = pickle.load(myfile)
except FileNotFoundError:
num = 0
if num < 5:
do_curl_stuff()
num += 1
with open("curl-output.txt", "wb") as myfile:
pickle.dump(num, myfile)
Two more things concerning your original code: You're making the first with block bigger than it needs to be. Once you've read the string into data, you don't need the file object anymore, so you can remove one level of indentation from everything except data = myfile.read().
Also, you don't need to close text_file manually. with will do that for you (that's the point).
Sounds more for a job scheduling with at command?
See http://www.ibm.com/developerworks/library/l-job-scheduling/ for different job scheduling mechanisms.
The first bug that is immediately obvious to me is that you are appending to the file even if data == finalrun. So when data == finalrun, you don't run curl but you do append another 'x' to the file. On the next run, data will be not equal to finalrun again so it will continue to execute the curl code.
The solution is of course to nest the code that appends to the file under the if statement.
Well there probably is an end of line jump \n character which makes that your file will contain something like xx\n and not simply xx. Probably this is why your condition does not work :)
EDIT
What happens if through the python command line you type
open('filename.txt', 'r').read() # where filename is the name of your file
you will be able to see whether there is an \n or not
Try using this condition along with if clause instead.
if data.count('x')==24
data string may contain extraneous data line new line characters. Check repr(data) to see if it actually a 24 x's.

Reading from, and then replacing all the text in a .txt file

I'm very new to Python (and coding in general, if I'm honest) and decided to learn by dipping into the Twitter API to make a weird Twitterbot that scrambles the words in a tweet and reposts them, _ebooks style.
Anyway, the way I have it currently set up, it pulls the latest tweet and then compares it to a .txt file with the previous tweet. If the tweet and the .txt file match (i.e., not a new tweet), it does nothing. If they don't, it replaces the .txt file with the current tweet, then scrambles and posts it. I feel like there's got to be a better way to do this than what I'm doing. Here's the relevant code:
words = hank[0]['text']
target = open("hank.txt", "r")
if words == "STOP":
print "Sam says stop :'("
return
else:
if words == target.read():
print "Nothing New."
else:
target.close()
target = open("hank.txt", "w")
target.write(words)
target.close()
Obviously, opening as 'r' just to check it against the tweet, closing, and re-opening as 'w' is not very efficient. However, if I open as 'w+' it deletes all the contents of the file when I read it, and if I open it as 'r+', it adds the new tweet either to the beginning or the end of the file (dependent on where I set the pointer, obviously). I am 100% sure I am missing something TOTALLY obvious, but after hours of googling and dredging through Python documentation, I haven't found anything simpler. Any help would be more than welcome haha. :)
with open(filename, "r+") as f:
data = f.read()// Redaing the data
//any comparison of tweets etc..
f.truncate()//here basically it clears the file.
f.seek(0)// setting the pointer
f.write("most recent tweet")// writing to the file
No need to close the file instance, it automatically closes.
Just read python docs on these methods used for a more clear picture.
I suggest you use yield to compare hank.txt and words line by line so that more memory space could be saved, if you are so focused on efficiency.
As for file operation, I don't think there is a better way in overwriting a file. If you are using Linux, maybe 'cat > hank.txt' could be faster. Just a guess.

Using variables in creating a file name

I'm pretty new to python, and am wondering if there's any way to put a variable into a file name, so that you can create files with different names each time.
In my particular case, I'd like to add date and time to the file name. If it was possible, this would work perfectly:
example = open("Path/to/file%s", "w") % str(datetime.now())
...but it doesn't. Is there any way to get that sort of functionality using a different approach? I've tried searching for an answer either way using multiple phrasings, but I can't find a yea or nay on it.
Thanks in advance guys.
EDIT: That was supposed to be an open() function, adjusted accordingly.
This should work. format() will replace the placeholder {0} in the string with the formatted datetime string (datestr).
>>> from datetime import datetime
>>> datestr = datetime.strftime(datetime.today(), "%Hh %Mm %Ss %A, %B %Y")
>>> examplefile = open("/home/michael/file{0}".format(datestr), 'w')
>>> print(examplefile)
<open file '/home/michael/file21h 20m 34s Monday, September 2012', mode 'w' at 0x89fcf98>
Modifying your answer to still use the old-style % formatting, you might do:
example = open("Path/to/file%s" % datetime.now(), "w")
Note that I've called open(), which is probably what you want to do (otherwise you're just creating a tuple). Also, using the %s format specifier automatically converts the argument to a string, so you don't really need the str().
The reason your example doesn't work has nothing to do with files.
example = ("Path/to/file%s", "w") % str(datetime.now())
The above is using the % operator with a tuple on the left, and a string on the right. But the % operator is for building strings based on a string template, which appears on the left of the %. Putting a tuple on the left just doesn't make sense.
You need to break what you want to do into more basic steps. You start with "I want to open a file whose name includes the current date and time". There is no way to directly do that, which is why you couldn't find anything about it. But a filename is just a string, so you can use string operations to build a string, and then open that string. So your problem isn't really "how do I open a file with the date/time in the name?", but rather "how do I put the date/time into a string along with some other information?". You appear to already know an answer to that question: use % formatting.
This makes sense; otherwise we'd have to implement every possible string operation for files as well as for strings. And also for everything else we use strings for. That's not the way (sane) programming works; we want to be able to reuse operations that already exist, not start from scratch every time.
So what you do is use string operations (that have nothing to do with files, and neither know nor care that you're going to eventually use this string to open a file) to build your filename. Then you pass that string to the file opening function open (along with the "w" string to specify that you want it writeable).
For example:
filename = "Path/to/file%s" % datetime.now()
example = open(filename, "w")
You can put it in one line if you want:
example = open("Path/to/file%s" % datetime.now(), "w")
But if you're relatively new to programming and to Python, I recommend you keep your small steps broken out until you're more comfortable with things in general.
All the answers posted here identify the problem correctly, that is your string formatting is not correct.
You should also check that the string you end up with is actually a valid file name for the operating system you are trying to create files on.
Your example doesn't generate a valid file name on Windows, and although will work on Linux, the file name created will not be what you expect:
>>> f = open(str(datetime.datetime.now()),'w')
>>> f.write('hello\n')
>>> f.close()
>>> quit()
-rw-r--r-- 1 burhan burhan 6 Sep 11 06:53 2012-09-11 06:53:04.685335
On Windows it doesn't work at all:
>>> open(str(datetime.datetime.now()),'w')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IOError: [Errno 22] invalid mode ('w') or filename: '2012-09-11 06:51:26.873000'
This would be a better option (2.6+):
filename = "Path/to/file/{0.year}{0.month}{0.day}".format(datetime.now())
For older versions of Python, you can use the classic option:
filename = "Path/to/file/%s" % datetime.strftime(datetime.now(),"%Y%m%d")

Categories

Resources