跳轉到內容

非程式設計師 Python 3 教程/檔案 I/O

來自華夏公益教科書

檔案 I/O

[編輯 | 編輯原始碼]

這是一個簡單的檔案 I/O (輸入/輸出) 示例

# Write a file
with open("test.txt", "wt") as out_file:
    out_file.write("This Text is going to out file\nLook at it and see!")

# Read a file
with open("test.txt", "rt") as in_file:
    text = in_file.read()

print(text)

輸出和檔案 test.txt 的內容是

This Text is going to out file
Look at it and see!

請注意,它在您執行程式的目錄中寫入了一個名為 test.txt 的檔案。字串中的 \n 告訴 Python 在它出現的地方插入一個換行符

檔案 I/O 的概述是

  • 使用 open 函式獲取檔案物件
  • 讀寫檔案物件(取決於開啟方式)
  • 如果您沒有使用 with 開啟檔案,您需要手動關閉它

第一步是獲取檔案物件。實現此目的的方法是使用 open 函式。格式為 file_object = open(filename, mode),其中 file_object 是要放置檔案物件的變數,filename 是包含檔名(字串),mode"rt"讀取檔案為文字,或 "wt"寫入檔案為文字(以及其他一些我們將在此處跳過的內容)。接下來,可以呼叫檔案物件函式。兩個最常見的函式是 readwritewrite 函式將字串新增到檔案的末尾。read 函式讀取檔案中下一個內容,並將其作為字串返回。如果沒有給出引數,它將返回整個檔案(如示例中所示)。

現在,我們之前製作的電話號碼程式的新版本

def print_numbers(numbers):
    print("Telephone Numbers:")
    for k, v in numbers.items():
        print("Name:", k, "\tNumber:", v)
    print()

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

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

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

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

def save_numbers(numbers, filename):
    out_file = open(filename, "wt")
    for k, v in numbers.items():
        out_file.write(k + "," + v + "\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 True:
    menu_choice = int(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 = input("Name: ")
        phone = input("Number: ")
        add_number(phone_list, name, phone)
    elif menu_choice == 3:
        print("Remove Name and Number")
        name = input("Name: ")
        remove_number(phone_list, name)
    elif menu_choice == 4:
        print("Lookup Number")
        name = input("Name: ")
        print(lookup_number(phone_list, name))
    elif menu_choice == 5:
        filename = input("Filename to load: ")
        load_numbers(phone_list, filename)
    elif menu_choice == 6:
        filename = input("Filename to save: ")
        save_numbers(phone_list, filename)
    elif menu_choice == 7:
        break
    else:
        print_menu()

print("Goodbye")

請注意,它現在包含檔案儲存和載入功能。以下是我的執行程式兩次後的輸出

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
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, "rt")
    while True:
        in_line = in_file.readline()
        if not in_line:
            break
        in_line = in_line[:-1]
        name, number = in_line.split(",")
        numbers[name] = number
    in_file.close()

def save_numbers(numbers, filename):
    out_file = open(filename, "wt")
    for k, v in numbers.items():
        out_file.write(k + "," + v + "\n")
    out_file.close()

首先,我們將檢視程式的儲存部分。首先,它使用命令 open(filename, "wt") 建立一個檔案物件。接下來,它遍歷併為每個電話號碼建立一個行,使用命令 out_file.write(k + "," + v + "\n")。這將寫入包含姓名、逗號、號碼和換行符的一行。

載入部分稍微複雜一些。它首先獲取檔案物件。然後,它使用 while True: 迴圈,一直迴圈直到遇到 break 語句。接下來,它使用 in_line = in_file.readline() 獲取一行。readline 函式在到達檔案末尾時將返回一個空字串。if 語句檢查這一點,並在發生這種情況時從 while 迴圈中 break。當然,如果 readline 函式沒有返回行尾的換行符,則無法判斷空字串是空行還是檔案末尾,因此換行符保留在 readline 返回的內容中。因此,我們必須去掉換行符。行 in_line = in_line[:-1] 透過刪除最後一個字元來實現這一點。接下來,行 name, number = in_line.split(",") 在逗號處將行拆分為名稱和號碼。然後將其新增到 numbers 字典中。

高階 .txt 檔案用法

[編輯 | 編輯原始碼]

你可能會對自己說,“好吧,我知道如何讀寫文字檔案,但如果我想列印檔案而不開啟另一個程式,怎麼辦?”

有幾種不同的方法可以實現這一點。最簡單的方法確實會開啟另一個程式,但所有操作都在 Python 程式碼中處理,不需要使用者指定要列印的檔案。此方法涉及呼叫另一個程式的子程序。

還記得我們在上面程式中寫入輸出的檔案嗎?讓我們使用該檔案。請記住,為了防止一些錯誤,此程式使用了下一章中的概念。請隨時在下一章之後重新訪問此示例。

import subprocess
def main():
    try:
        print("This small program invokes the print function in the Notepad application")
        #Lets print the file we created in the program above
        subprocess.call(['notepad','/p','numbers.txt'])
    except WindowsError:
        print("The called subprocess does not exist, or cannot be called.")

main()

subprocess.call 接受三個引數。在本文件的示例中,第一個引數應該是您要從中呼叫列印子程序的程式名稱。第二個引數應該是該程式中的特定子程序。為簡單起見,只需瞭解在本文件中,'/p' 是用於透過指定應用程式訪問印表機的子程序。最後一個引數應該是您要傳送到列印子程序的檔名稱。在本例中,它與本章前面使用的檔案相同。

現在修改字典部分中的成績程式,使其使用檔案 I/O 來儲存學生的記錄。

解決方案

現在修改字典部分中的成績程式,使其使用檔案 I/O 來儲存學生的記錄。

assignments = ['hw ch 1', 'hw ch 2', 'quiz   ', 'hw ch 3', 'test']
students = { }

def load_grades(gradesfile):
    inputfile = open(gradesfile, "r")
    grades = [ ]
    while True:
        student_and_grade = inputfile.readline()
        student_and_grade = student_and_grade[:-1]
        if not student_and_grade:
            break
        else:
            studentname, studentgrades = student_and_grade.split(",")
            studentgrades = studentgrades.split(" ")
            students[studentname] = studentgrades
    inputfile.close()
    print("Grades loaded.")

def save_grades(gradesfile):
    outputfile = open(gradesfile, "w")
    for k, v in students.items():
        outputfile.write(k + ",")
        for x in v:
            outputfile.write(str(x) + " ")
        outputfile.write("\n")
    outputfile.close()
    print("Grades saved.")

def print_menu():
    print("1. Add student")
    print("2. Remove student")
    print("3. Load grades")
    print("4. Record grade")
    print("5. Print grades")
    print("6. Save grades")
    print("7. Print Menu")
    print("9. Quit")

def print_all_grades():
    if students:
        keys = sorted(students.keys())
        print('\t', end=' ')
        for x in assignments:
            print(x, '\t', end=' ')
        print()
        for x in keys:
            print(x, '\t', end=' ')
            grades = students[x]
            print_grades(grades)
    else:
        print("There are no grades to print.")

def print_grades(grades):
    for x in grades:
        print(x, '\t', end=' ')
    print()

print_menu()
menu_choice = 0
while menu_choice != 9:
    print()
    menu_choice = int(input("Menu Choice: "))
    if menu_choice == 1:
        name = input("Student to add: ")
        students[name] = [0] * len(assignments)
    elif menu_choice == 2:
        name = input("Student to remove: ")
        if name in students:
            del students[name]
        else:
            print("Student:", name, "not found")
    elif menu_choice == 3:
        gradesfile = input("Load grades from which file? ")
        load_grades(gradesfile)
    elif menu_choice == 4:
        print("Record Grade")
        name = input("Student: ")
        if name in students:
            grades = students[name]
            print("Type in the number of the grade to record")
            print("Type a 0 (zero) to exit")
            for i,x in enumerate(assignments):
                print(i + 1, x, '\t', end=' ')
            print()
            print_grades(grades)
            which = 1234
            while which != -1:
                which = int(input("Change which Grade: "))
                which -= 1
                if 0 <= which < len(grades):
                    grade = input("Grade: ") # Change from float(input()) to input() to avoid an error when saving
                    grades[which] = grade
                elif which != -1:
                    print("Invalid Grade Number")
        else:
            print("Student not found")
    elif menu_choice == 5:
        print_all_grades()
    elif menu_choice == 6:
        gradesfile = input("Save grades to which file? ")
        save_grades(gradesfile)
    elif menu_choice != 9:
        print_menu()


非程式設計師 Python 3 教程
 ← 字串復仇 檔案 I/O 處理不完美 → 
華夏公益教科書