Unsure how to resolve this overwriting error - python-3.x

I have a function that prompts the user to enter their firstname, Surname, Password and id.
What I realised is that every time I run this function it just overwrites my previous values for these 4 variables. What I want to achieve is to be able to run this function and then write the details to a text file and permanently save it and then be able to add another user's details and upload it. Currently when I restart the program and run my student registeration function it's just overwriting my previous variables. Perhaps I shouldn't store my data in variables? Any tips on how to resolve this?
f = open("studentlogindetails.txt", "a+")
f.write("\n" + firstname + " " + surname + " " + universitypassword + " " + universityid)
f.close()

The a+ mode is used to open a file to be read and appended to. Because it is intended to be read, the cursor is placed at the very beginning of the file under the assumption that you are going to immediately try to read from the file. When you try to write, the data written starts wherever the cursor is. You want to place the cursor at the end of the file before you write.
If you don't need to read information and only write, you can use the a mode instead, which opens the file for appending information and places the cursor at the end of the file.
Alternatively, you can manually move the cursor to the end of the file with the f.seek method.
The documentation states:
fileObject.seek(offset[, whence])
offset − This is the position of the read/write pointer within the file.
whence − This is optional and defaults to 0 which means absolute file positioning, other values are 1 which means seek relative to the current position and 2 means seek relative to the file's end.
So, if you want to keep using the a+ mode, you have to remember to use f.seek(0, 2) to place the cursor 0 bytes from the end of the file before writing.
The available file-open modes and their use can be seen below:
r: Opens the file in read-only mode. Starts reading from the beginning of the file and is the default mode for the open() function.
rb: Opens the file as read-only in binary format. Places the cursor at the start of the file.
r+: Opens a file for reading and writing. Places the cursor at the beginning of the file.
w: Opens in write-only mode. Places the cursor at the beginning of the file. This will overwrite any existing file with the same name. It will create a new file if one with the same name doesn't exist.
wb: Same behavior as w, except the file is opened in binary mode.
w+: Opens a file for writing and reading. Replaces all content and creates the file if it doesn't exist. This mode is used when you need to write to an empty-file and potentially read from it later in your code (before closing).
wb+: Same behavior as w+ except the file is in binary mode.
a: Opens a file for appending new information to it. The cursor is placed at the end of the file. A new file is created if one with the same name doesn't exist.
ab: Same behavior as a except the file is in binary mode.
a+: Opens a file for both appending and reading. The cursor is placed at the beginning of the file.
ab+: Same as a+ except the file is in binary mode.
Information for the modes was pulled and edited from here.

You should use the with keyword and write your data, you can pass the append argument as well.
with open("studentlogindetails.txt", "a") as f:
# Using f-strings
f.write(f"{firstname} {surname} {universitypassword} {universityid}")
Using with ensures all resources are cleaned up even if an error occurs.
Note: If this is just a project you're playing around with to learn how to write text files, then you're probably fine, however, if this is going to be used in production, it's best you use a proper database.
It looks like your writing some user data at a University, you can use the ID that is given to every student and employee as the primary key.
Also, don't store passwords in plain text, and don't implements your own hashing algorithm. Many robust solutions exist.

Related

Input on multiple lines

I try to write a short program which takes multiple pdf files and merges them into one file. The whole thing should operate over a command line.
I use the argparse-package from python. The program works when I call it and give exactly two files to merge. But I want it to be more flexible. Concrete, what I want to do is calling the program, give the first file and hit enter. Then it should ask for the second file: I give it and hit enter, and so on until I hit enter without inserting any file. Like this, the program should know that all files are given.
Every time I hit enter, the program executes and I don't have any chance to do anything else. I searched for a workaround but didn't find any.
You can use input:
files = []
file = input("Your file: ").strip()
while file:
files.append(file)
file = input("Your file: ").strip()
print(f"Files to process: {files}")

Opening the file in r+ mode but not able to truncate it?

I am failing to truncate a previously created file by opening it in r+ mode given that r+ Open for reading and writing. The stream is positioned at the beginning of the file.
Reference -> here
from sys import argv
script, filename = argv
print(f"We're going to erase {filename}")
print("If you don't want that, hit Ctrl+C (^C).")
print("If you do want that, hit return")
input("?")
print("Opening the file...")
target = open(filename, 'r+')
print(target.read())
print("Truncating the file, Goodbye!")
target.truncate()
The truncate method will resize the file so that it ends at the current file position (if you don't pass it a value for the size argument). When you read the file, you move the current position in the file from the start to the end. That means the truncation does nothing, since you're making the new end of the file the same as the old end position.
If you want to call truncate with no arguments, you need to seek back to the beginning of the file first, or alternatively, call truncate(0) to tell it to make the new file size zero bytes.
The "truncate" method takes an optional size parameter. If you do not specify that parameter, it uses the default location into the file. I assume since you just read the file, the default location is at the end of the file -- so nothing follows the current location and nothing gets truncated. Try passing a zero (0) to the truncate method and see what happens. You might also try opening the file with 'rw+'.

Open file mode string w+

I know what io.open(file, "w") does, it indicates writting. However I have encountered io.open(file, "w+") and can't find what "w+" does?
io.open just uses fopen of C. you could check the manual of fopen in C.
w: Truncate file to zero length or create text file for writing.
The stream is positioned at the beginning of the file.
w+: the same as w, besides the handle returned could be used for
reading.
From the reference manual io.open
The mode string can be any of the following:
"r": read mode (the default);
"w": write mode;
"a": append mode;
"r+": update mode, all previous data is preserved;
"w+": update mode, all previous data is erased;
"a+": append update mode, previous data is preserved, writing is only allowed at the end of file.
update mode here means, both input and output may be performed on the
associated file.
I tested this in Lua 5.1 running on OpenWRT and found
file=io.open("/usr/share/result","w")
was the same as
file=io.open("/usr/share/result","w+")
Both actions erased the current content of the file and re-wrote it.
When I tried
file=io.open("/usr/share/result","a")
The file was appended to - it got longer and longer each time my code ran.
So I don't think there is a difference.

What is a "buffer" in VIM?

When VIM refers to a file im editing as a "buffer"...what exactly does it mean? Whenever I edit the file in shell or in the application, it refers to the copy of the file as a buffer. I was curious as to what exactly this meant, but couldn't find anything on it. Any help would be appreciated.
From :help windows-intro, as linked by icktoofay in a comment:
A buffer is the in-memory text of a file ... [which is] loaded into memory for editing. The original file remains unchanged until you write the buffer to the file.
That is, a buffer represents the actual loaded/working data itself.
You can think of it as similar to the Windows clipboard. You can use it to cut, copy and paste text snippets.
But you can have multiple "buffers" open at the same time. And each buffer can have a name.
See VI Tutorial: Manipulating Text:
A named buffer is another method to move or duplicate text... first position the cursor at the material you want to copy. Next make a copy of the desired text by using the yank command. This places the copied text into a temporary buffer...

In Vim, what is the "alternate file"?

I just ran :help registers in Vim and noticed that # 'contains the name of the alternate file'.
I have seen an example for renaming files that goes like this:
" Save the current file, foo.txt, as bar.txt
:w bar.txt
" Start editing bar.txt
:e#
So apparently in that case, the file you just saved out is the "alternate file."
Can someone give me a more general definition for the "alternate file" and what else you might use it for?
The alternate file is the file that was last edited in the current window. Actually when you use some command to open a new buffer, if the buffer that was displayed had a filename associated with it, that filename is recorded as alternate file name.
See :help alternate-file.
Very useful for...
Pasting in the name of a file I've just been looking at into the current file.
You can use <C-R># for this in insert mode or "#p in normal mode.
Not that useful for...
Jumping back and forth between two files. It does the job very well, but this is just something I don't generally need to do.
Even in the example given, I'd probably use:saveas bar.txt instead.
An Example:
Say if you're doing a bit of C programming and want to call some function. You can't remember the name of the function, so you place a mark on your current location mA and jump into several different files using tags or grep to find out where the function is declared and what it's actually called.
Ah - found it. You can copy the name and return to the mark yiw'A
Uh-oh - we also need to #include the file! Easy - just use the alternate file name register to paste the file name in... Gi#include"<C-R>#"
Be pleased that you've avoided the distraction of having to go back to the function's declaration and copy out the file name via :let #"=#% or something similar.
What I'd rather do when jumping between files:
When editing two files, it's probably easier to split them, so you can keep both on screen at the same time. If I'm editing 2 files I'll usually be comparing them in some way.
Usually I'm interested in 1-3 files (any more and I get confused). I'll often jump into or directly open many other files. Marking the interesting files, or traversing the jump list is usually the way to get around in this case.
If you're editing C/C++ where you're switching between a file and it's header, use a plugin! It will be much more convenient.
I use it in the buffer context to return to the last buffer that I was editing
vim foo bar
:n
:e#
will take you back to foo in that case
I 've always interpreted the "alternate file" as being the "previous file", so it is an handy way to jump back to the buffer you were editing.

Resources