0

So basically I have my code get all the input from the basketballs, dodgeballs, rackets tennisballs etc from the user, I can log them into a InvenData.txt file but how would I actually keep them their after the application closes? Im using datetime, is there also a method that I can use that identifies months? This is basically how I want it to work...

Fill out the table (already done, receives input) then, take that input and orderly put it into a file (Done that as well and it saves the month in the data as well) And then I want it to stay there. And AS LONG as they are still in THAT Current month it will update THAT Month's data and when the month changes, throw, it will throw the data down into the same format as the last month, but just further down the Data file

        file.write("Basketballs: " + ballEntry.get() + "\n")
        file.write("Dodgeballs: " + dodgeEntry.get() + "\n")
        file.write("Rackets: " + racketEntry.get() + "\n")
        file.write("Tenisballs: " + TenisballlEntry.get() + "\n")
        file.write("Total: " + totalFile + "\n")
        file.write("Last updated on: " + dateTimeFile + "\n")

The file looks like this when all the user puts their input in

Basketballs: 423
Dodgeballs: 234
Rackets: 253
Tenisballs: 235
Total: 1145
Last updated on: 2020-01-14

EXAMPLE OF WHAT I'D WANT IT TO DO THE NEXT MONTH

Basketballs: 4223
Dodgeballs: 23324
Rackets: 2453
Tenisballs: 2335
Total: 11435
Last updated on: 2020-02-01

Thanks fore reading!

with open('InvenData.txt', 'r') as f:

    filestring1 = file.write("Current Position: %d" % (fileLinePos) + "\n")
    filestring2 = file.write("Basketballs: " + ballEntry.get() + "\n")
    filestring3 = file.write("Dodgeballs: " + dodgeEntry.get() + "\n")
    filestring4 = file.write("Rackets: " + racketEntry.get() + "\n")
    filestring5 = file.write("Tenisballs: " + TenisballlEntry.get() + "\n")
    filestring6 = file.write("Total: " + totalFile + "\n")
    filestring7 = file.write(timeString)
    file.close()

    list = [filestring1, filestring2, filestring3, filestring4, filestring5, filestring6, filestring7]
    lines = list(f)
    for line in lines:
        file.write(line)

print("Data has been registered successfully!")

messagebox.showinfo('Success!', 'Data added to data centre successfully!')
Daniel B.
  • 1,254
  • 1
  • 16
  • 35
Drafter
  • 21
  • 6

1 Answers1

2

the datetime module can identify the time from year down to microseconds.

You can create a string using datetime.datetime.strftime(format), which uses standard C substitutions to create a string based on a given datetime.

if you use datetime.datetime.now(), you can use the current date:

import datetime

time = datetime.datetime.now()
template = 'Last updated on: %Y-%m-%d'
time_string = time.strftime(template)

print(time_string)

# prints "Last updated on: 2020-01-14"

The way you have described the file format, the final line should always contain the date of the last entry, so you just need to pull the lines up to the last entry and extract the month. To extract, you can use datetime.datetime.strptime(input, format) with the same format string:

stripped = datetime.datetime.strptime(time_string, fmt)
print(stripped)
print(stripped.month)

# 2020-01-14 00:00:00
# 1

As far as working with the data in the file ... it sounds like an XY problem, so I'll first address what you're asking, then suggest a different tactic.

You want to update the data if it is the same month, and overwrite the data if it is a new month. You can't simply insert data into the middle of the file: You have access to the read/write pointer (i.e. the current character in the file), and can read or write at that position.

You could use an algorithm something like this:

  1. Open the file for reading and writing without truncating ('r+')
  2. capture the current cursor position with file.tell() (this will start at 0)
  3. read lines until you have reached a date line. To do this, you can simply check with datetime.datetime.strptime(line, "Last updated on: %Y-%m-%d"). An ValueError will be raised if it does not match.
  4. if there are more lines, capture the position again with file.tell().
  5. Repeat until there are no more lines to read. Be sure you don't update the position at the end of the file!
  6. You now have the position of the start of the last month's entry in the file. Overwrite the remainder of the file with the new inventory and date.
  7. There may be characters remaining, delete them.
  8. Close the file

Note that I close the file at the end. As a general rule, files should be closed as soon as possible (Why should I close files in Python?)

It's for this same reason, as well as for simplicity, that I would suggest a different tactic. Read your entire file into a list of strings, one string per line:

with open(filename, 'r') as f:
    lines = list(f)

By using the "with as" syntax, the file will be closed after the lines are read. Now find the beginning of the final date entry (use the same method from the previous algorithm, but in the list instead.

Modify the remaining lines with your new values.

Now open the file in write mode. This truncates the file (i.e. deletes everything!):

with open(filename, 'w') as f:
  for line in lines:
    f.write(line)

You could also track the line number and do f.readline() until you have read all but the lines you want to modify, then do f.write(line) from that point forward.

The basic idea is: don't keep the file open longer than you have to. Do your modifications in memory, then write them to the file quickly and close the file again. Unless you're using a huge file, this shouldn't be an issue, and with the format of your file I can't imagine it getting very big.

As an aside, all of this would likely be simplified if you added a header to your file containing the character position (using seek, described in the algorithm) to track the starting character of the last entry in the file

Daniel B.
  • 1,254
  • 1
  • 16
  • 35
  • Thanks! This helped! But now how would I permanently save data into a file, and than call on that data through the file and into my code? Kinda like a config.yml where you can call upon certain data values from your code. – Drafter Jan 16 '20 at 19:22
  • I've updated the response. Generally though, you shouldn't work directly in the file. Use the file to read information into your program's memory and work on that, then when it's ready, overwrite the file with the new inventory. – Daniel B. Jan 16 '20 at 20:14
  • Thanks, that really helpful as well. But how do I PERMANENTLY save it into the data. So that even if I were to re open it, it would still stay? – Drafter Jan 17 '20 at 03:24
  • The write operation is finalized when you close the file object (or at the end of the `with open as` block.) Some data may be written to disk before that, but you can't guarantee that it is fully written until the file handle is closed. – Daniel B. Jan 17 '20 at 17:45
  • Getting an error `TypeError: 'list' object is not callable` I added the code to the bottom of my original post (I know it's ugly lol) – Drafter Jan 20 '20 at 05:02
  • This isn't really relevant to your original question anymore; If you make another question with the latest snippet I can answer more in depth there. But your issue is that you are overwriting the function list() with a variable list = [None, None, ... None] (because file.write() returns None). So when you call list(f), it is trying to interpret a list object as a function, but that list object is not callable. – Daniel B. Jan 20 '20 at 15:58