Αρχεια (I/O)

Ενα απλο παράδειγμα οπου χειριζομαστεε ένα αρχείο και διαβάζουμε τα περιεχομενά του (I/O απο το input/output):
#Write a file
out_file = open("test.txt","w")
out_file.write("This Text is going to out file\nLook at it and see\n")
out_file.close()

#Read a file
in_file = open("test.txt","r")
text = in_file.read()
in_file.close()

print text,
To αποτελεσμα και τα περιεχομενα του αρχειου test.txt είναι:
This Text is going to out file
Look at it and see
Παρατηρηστε οτι δημιουργηθηκε ένα αρχειο με το ονομα test.txt στον φακελο (κατάλογο) που έτρεξε το προγραμμά μας. Το \n στην συμβολοσειρα λεει στην Python να γραψει μια νέα (newline) στο σημείο οπου το συνανταει.

Μια περιληψη του χειρισμου των αρχείων:

  1. Πάρε ένα αντικειμενο - αρχείο με την συνάρτηση open.
  2. Διάβασε (read) η γραψε (write) στο αρχείο (ανάλογα με τον τροπο που άνοιξε)
  3. Κλεισε

Το πρωτο βημα είναι να πάρουμε ενα αρχείο. Το παιρνουμε με την συνάρτηση open function. Η συνταξη είναι file_object = open(filename,mode) οπου file_object είναι η μεταβλητη που θα τοποθετηθει στο αντικείμενο , το filename είναι μια συμβολοσειρα με το ονομα του αρχείου, και το mode είναι είτε "r" για ανάγνωση (read) είτε "w" για εγγραφη (write) στο αρχειο. Επειτα καλουνται οι συναρτήσεις αντικειμενων. Οι πιο συνηθεις απο αυτες ειναι η read και η write. Η συνάρτηση write προσθετει μια συμβολοσειρα στο τελος του αρχειου. Η συνάρτηση read διαβαζει το επομενο πραγμα μεσα στο αρχείο και το επιστρεφει ως συμβολοσειρα. Αν δεν δωθει παράμετρος, θα επιστραφει ολοκληρο το αρχείο (οπως συμβαινει στο παράδειγμα).

Και τωρα η νεοτερη έκδοση του προγραμματος των τηλεφωνικων αριθμων που ειχαμε γραψει παλιοτερα:

import string

true = 1
false = 0

def print_numbers(numbers):
    print "Telephone Numbers:"
    for x in numbers.keys():
        print "Name: ",x," \tNumber: ",numbers[x]
    print

def add_number(numbers,name,number):
    numbers[name] = number

def lookup_number(numbers,name):
    if numbers.has_key(name):
        return "The number is "+numbers[name]
    else:
        return name+" was not found"

def remove_number(numbers,name):
    if numbers.has_key(name):
        del numbers[name]
    else:
        print name," was not found"


def load_numbers(numbers,filename):
    in_file = open(filename,"r")
    while true:
        in_line = in_file.readline()
        if in_line == "":
            break
        in_line = in_line[:-1]
        [name,number] = string.split(in_line,",")
        numbers[name] = number
    in_file.close()

def save_numbers(numbers,filename):
    out_file = open(filename,"w")
    for x in numbers.keys():
        out_file.write(x+","+numbers[x]+"\n")
    out_file.close()
    

def print_menu():
    print '1. Print Phone Numbers'
    print '2. Add a Phone Number'
    print '3. Remove a Phone Number'
    print '4. Lookup a Phone Number'
    print '5. Load numbers'
    print '6. Save numbers'
    print '7. Quit'
    print
phone_list = {}
menu_choice = 0
print_menu()
while menu_choice != 7:
    menu_choice = input("Type in a number (1-7):")
    if menu_choice == 1:
        print_numbers(phone_list)
    elif menu_choice == 2:
        print "Add Name and Number"
        name = raw_input("Name:")
        phone = raw_input("Number:")
        add_number(phone_list,name,phone)
    elif menu_choice == 3:
        print "Remove Name and Number"
        name = raw_input("Name:")
        remove_number(phone_list,name)
    elif menu_choice == 4:
        print "Lookup Number"
	name = raw_input("Name:")
        print lookup_number(phone_list,name)
    elif menu_choice == 5:
        filename = raw_input("Filename to load:")
        load_numbers(phone_list,filename)
    elif menu_choice == 6:
        filename = raw_input("Filename to save:")
        save_numbers(phone_list,filename)
    elif menu_choice == 7:
        pass
    else:
        print_menu()
print "Goodbye"
Βλεπουμε πως μπορουμε να σωσουμε και να φορτωσουμε αρχεία. Να κάποια αποτελέσματα που ειχα τρεχοντάς το δυο φορες:
> python tele2.py
1. Print Phone Numbers
2. Add a Phone Number
3. Remove a Phone Number
4. Lookup a Phone Number
5. Load numbers
6. Save numbers
7. Quit

Type in a number (1-7):2
Add Name and Number
Name:Jill
Number:1234
Type in a number (1-7):2
Add Name and Number
Name:Fred 
Number:4321
Type in a number (1-7):1
Telephone Numbers:
Name:  Jill     Number:  1234
Name:  Fred     Number:  4321

Type in a number (1-7):6
Filename to save:numbers.txt
Type in a number (1-7):7
Goodbye
> python tele2.py
1. Print Phone Numbers
2. Add a Phone Number
3. Remove a Phone Number
4. Lookup a Phone Number
5. Load numbers
6. Save numbers
7. Quit

Type in a number (1-7):5
Filename to load:numbers.txt
Type in a number (1-7):1
Telephone Numbers:
Name:  Jill     Number:  1234
Name:  Fred     Number:  4321

Type in a number (1-7):7
Goodbye

Τα νεα κομμάτια στον κωδικα είναι:

def load_numbers(numbers,filename):
    in_file = open(filename,"r")
    while 1:
        in_line = in_file.readline()
        if len(in_line) == 0:
            break
        in_line = in_line[:-1]
        [name,number] = string.split(in_line,",")
        numbers[name] = number
    in_file.close()
def save_numbers(numbers,filename):
    out_file = open(filename,"w")
    for x in numbers.keys():
        out_file.write(x+","+numbers[x]+"\n")
    out_file.close()

Ας εξετάσουμε πρωτα το κομμάτι του κωδικα που σωζει το αρχείο. Αρχικά δημιουργει το αρχείο με την εντολη open(filename,"w"). Επειτα συνεχιζει γραφοντας σε μια νεα γραμμη τον κάθε τηλεφωνικο αριθμο με την εντολη out_file.write(x+","+numbers[x]+"\n"). Αυτη γραφει μια γραμμή που περιεχει το ονομα, ένα κομμα, τον αριθμο και συνεχιζει με μια νέα γραμμή.

Το κομμάτι που φορτωνει το αρχείο είναι λιγο πιο περιπλοκο. Ξεκιναει παίρνοντας ένα αρχείο. Μετα χρησιμοποιει τον βρογχο while 1: για να τον κρατησει μέχρι να συνατησει μια εντολη break. Υστερα παιρνει μια νεα γραμμη με το in_line = in_file.readline(). Η συνάρτηση getline θα επιστρέψει μια αδεια συμβολοσειρα (len(string) == 0) οταν φτασει στο τελος του αρχείου. Η δήλωση if ελεγχει για κάτι τετοιο και σπαει (break) τον βρογχο του while οταν αυτό συμβεί. Βέβαια, αν η συνάρτηση readline δεν επεστρεφε την νεα γραμμή στο τέλος καθε γραμμης δεν θα υπηρχε τροπος να καταλαβουμε αν είμαστε σε μια άδεια γραμμη η στο τελος του αρχείου, και έτσι η νεα γραμμη ειναι στα αριστερα αυτου που επιστρεφει η getline. Γιαυτο πρεπει να ξεφορτωθουμε την νεα γραμμή. Η εντολη in_line = in_line[:-1] το καταφερνει διαγράφοντας τον τελευταιο χαρακτηρα. Η γραμμη [name,number] = string.split(in_line,",") χωριζει την γραμμη με βάση το κομμα σε ονομα και σε τηλεφωνο. Η γραμμή αυτη μετα, προστιθεται στο μητρωο numbers.

Ασκησεις

Μετατρέψτε το προγραμμα βαθμολογίας απο το κεφάλαιο 11 έτσι ωστε να χρησιμοποιει αρχεια και να κραταει αρχείο των μαθητων.