python:文件和异常处理

1、文本输入和输出

# 使用open函数创建一个文件对象,使用这个对象的read和write方法进行读写数据
# 打开文件:fileVariable=open(filename,mode)
"""
mode:
    r:读取打开
    w:写入,会覆盖原有的
    a:追加
    rb:二进制打开读出文件
    wb:二进制打开写入文件
"""
#  input = open(r"C:\","r")
# 或 input=open("C:\\","r")

1.1 写入数据

"""
    1.1  写入数据:
    read():str
    readline():str
    readlines():list
    write(str):None     换行需要显示写"\n"
    close():None
"""


def main():
    outfile = open(r"C:\Users\Lenovo\Desktop\1.txt", "w")

    # write to file
    outfile.write("Hello\n")
    outfile.write("World\n")
    outfile.write("China")

    outfile.close()


main()

1.2 测试文件是否存在

"""
    1.2 测试文件是否存在,防止意外删除之前文件数据
"""
import os.path
def main():
    if os.path.isfile(r"C:\Users\Lenovo\Desktop\1.txt"):
        print("已经存在文件")

main()

1.3 读取文件数据

"""
    1.3 读取文件数据
    read(number):str  读取指定数目number的字符
    read():str      读取所有的字符
    readline():str 读取下一行
    readlines():list 读取所有行并放入一个字符串列表
    repr(s):返回s的原始字符串
"""


def main():
    print("use by read()")
    infile = open(r"C:\Users\Lenovo\Desktop\1.txt","r")
    s1 = infile.read(7)
    print(s1)
    # 输出结果:(包括一个换行符)
    # Hello
    # W
    print(repr(s1))
    # 输入出结果:'Hello\nW'
    infile.close()

    print("use by readline()")
    infile1 = open(r"C:\Users\Lenovo\Desktop\1.txt", "r")
    line = infile1.readline()
    while line != '':  # 这里不是空格
        print(repr(line))
        line = infile1.readline()
    infile1.close()
    # 输出:
    # 'Hello\n'
    # 'World\n'
    # 'China'

    print("use by readline()")
    infile2 = open(r"C:\Users\Lenovo\Desktop\1.txt", "r")
    for line in infile2:
        print(line)
    infile2.close()
    # 输出:(注意:是去掉repr())
    # Hello
    #
    # World
    #
    # China

    print("use by readines()")
    infile3 = open(r"C:\Users\Lenovo\Desktop\1.txt", "r")
    list=infile3.readlines()
    print(list)
    for item in list:
        print(repr(item),end=" ")
    infile3.close()
    # 输出:
    # ['Hello\n', 'World\n', 'China']
    # 'Hello\n' 'World\n' 'China'
main()

1.4 案例:复制

"""
    对于小文件,可以用read(),readline()s读取所有数据,
    但是对应于大文件,可以选择while line!="" + readline()for line infile + readline()
"""
import os.path
import sys


def main():
    f1 = input("Enter a source file:").strip()  # C:\Users\Lenovo\Desktop\1.txt
    f2 = input("Enter a target file:").strip()

    if os.path.isfile(f2):
        print(f2 + "already exit")
        sys.exit()

    infile = open(f1, "r")
    outfile = open(f2, "w")

    countLine = countChar = 0
    for lines in infile:
        countLine += 1
        countChar += len(lines)  # 有包括换行符
        outfile.write(lines)
    print("countlines=",countLine,"countChar=",countChar)

    infile.close()
    outfile.close()

main()

在这里插入图片描述
python:文件和异常处理_第1张图片
不删文件,再试一次效果:
python:文件和异常处理_第2张图片

1.5 追加数据

def main():
    outfile=open(r"C:\Users\Lenovo\Desktop\1.txt","a")
    outfile.write("\npython is interested\n")
    outfile.close()
main()

python:文件和异常处理_第3张图片

1.6 文件对话框

核心代码:

from tkinter.filedialog import askopenfilename
from tkinter.filedialog import asksaveasfilename

filenameforReading =askopenfilename()
print("You can read from "+filenameforReading)

filenameforWriting = asksaveasfilename()
print("You can save data to "+filenameforWriting)

完整代码:

from tkinter import *
from PIL import ImageTk
from tkinter.filedialog import askopenfilename
from tkinter.filedialog import asksaveasfilename


class FileEditor:
    def __init__(self):
        window = Tk()
        window.title("文本编辑器")

        menubar = Menu(window)
        window.config(menu=menubar)

        fileSaveOpenMenu = Menu(menubar, tearoff=0)
        menubar.add_cascade(label="File", menu=fileSaveOpenMenu)

        fileSaveOpenMenu.add_command(label="Save", command=self.save)
        fileSaveOpenMenu.add_command(label="Open", command=self.open)
        fileSaveOpenMenu.add_command(label="Clear", command=self.clear)

        frame0 = Frame(window)
        frame0.grid(row=1, column=1, sticky=W)
        saveImage = ImageTk.PhotoImage(file="C:/Users/Lenovo/Desktop/save.png")
        openImage = ImageTk.PhotoImage(file="C:/Users/Lenovo/Desktop/open.png")
        clearImage = ImageTk.PhotoImage(file="C:/Users/Lenovo/Desktop/clear.png")
        Button(frame0, image=saveImage, command=self.save).grid(row=1, column=1, sticky=W)
        Button(frame0, image=openImage, command=self.open).grid(row=1, column=2)
        Button(frame0, image=clearImage, command=self.clear).grid(row=1, column=3)

        frame1 = Frame(window)
        frame1.grid(row=2, column=1)
        scrollbar = Scrollbar(frame1)
        scrollbar.pack(side=RIGHT, fill=Y)

        self.text = Text(frame1, width=100, height=50, wrap=WORD, yscrollcommand=scrollbar.set)
        self.text.pack()
        scrollbar.config(command=self.text.yview)  # create a event loop

        window.mainloop()

    def open(self):
        filenameforReading = askopenfilename()
        infile = open(filenameforReading, "r")
        self.text.insert(END, infile.read())

        infile.close()

    def save(self):
        filenameforWriting = asksaveasfilename()
        outfile = open(filenameforWriting, "w")
        outfile.write(self.text.get(1.0, END))
        outfile.close()

    def clear(self):
        self.text.delete(1.0, END)

FileEditor()

python:文件和异常处理_第4张图片

1.7 从网站获取数据

import urllib.request


def main():
    url = input("Enter a URL for a file:").strip()
    # https://cs.armstrong.edu/liang/data/Lincoln.txt
    infile = urllib.request.urlopen(url)
    s = infile.read().decode()

    counts = countLetters(s.lower())
    for i in range(len(counts)):
        if counts[i] != 0:
            print(chr(ord('a') + i) + " appears " + str(counts[i]) + (" times" if counts[i] > 0 else " time"))


def countLetters(s):
    counts = 26 * [0]
    for ch in s:
        if ch.isalpha():
            counts[ord(ch) - ord('a')] += 1
    return counts

main()

1.8 指定文件删除指定字符串,否则生成空文件

import os.path


def readFromTxt(s):
    # C:\Users\Lenovo\Desktop\1.txt
    filename = input("Enter the source txt's name").strip()
    stringLine = ''
    if not os.path.isfile(filename):
        print(filename + "does not exit")
    else:
        try:
            inFile = open(filename, "r")
            stringLine = inFile.read().replace(s, "")
        except nameError:
            print("Something wrong happens.")
        inFile.close()
    return filename, stringLine


def writeToTxt(filename, s):
    outFile = open(filename, "w")
    outFile.write(s)
    outFile.close()


def main():
    item = input("Enter the string you wanna delete in the file")
    filename, s = readFromTxt(item)
    writeToTxt(filename, s)


main()

2.异常处理

# 异常:堆栈回溯
# try:
#	<body>
# except
# <handler>
def main():

    while True:
        try:
            filename = input("Enter a filename:").strip()  # C:\Users\Lenovo\Desktop\1.txt
            infile = open(filename, 'r')
            break
        except IOError:
            print("File " + filename + " does not exit.Try again.")

    counts = 26 * [0]

    for line in infile:
        countLetters(line.lower(), counts)

    for i in range(len(counts)):
        if counts[i] != 0:
            print(chr(ord('a') + i) + " appears " + str(counts[i]) + (" times" if counts[i] > 1 else " time"))

    infile.close()


def countLetters(line, counts):
    for ch in line:
        if ch.isalpha():
            counts[ord(ch) - ord('a')] += 1


main()

如果一个异常出现,匹配一个异常类型,则该类型下的处理代码将执行。剩余语句不执行。
如果异常不匹配except字句中的异常名,则传递给函数的调用者;如果没有找到匹配异常的处理器,则是一个未知的异常,终止程序显示错误信息。

try:
	< body>
except < ExceptionType1>:
		< handler1 >
except < ExceptionType2>:
		< handler2 >
	...
else:
	< process_else>
finally:

	<process_finally>

案例:

def main():
    try:
        a, b, c = eval(input("Enter three number , separated by comma:"))
        result = a / b + c
        print("Result=", result)

    except ZeroDivisionError:
        print("divided by zero!")
    except SyntaxError:
        print("A comma may be missing in the input")
    except:
        print("Something wrong in the input")
    else:
        print("No exceptions")
    finally:
        print("End")


main()

子类类型异常要在父类异常前

3.抛出异常

CircleWithException.py

# 抛出异常
# 异常在对象--类实例为对象--类中函数抛出异常 raise ExceptionClass("Something is wrong")
# 例如输入意外的负数抛异常:raise Runtime("wrong argument")
import math

class Circle:
    def __init__(self, radius):
        self.setRadius(radius)

    def getRadius(self):
        return self.__radius

    def setRadius(self, radius):
        if radius < 0:
            ex = RuntimeError("Negative radius")
            raise ex
            # 或 raise RuntimeError("Negative radius")
        else:
            self.__radius = radius

    def getArea(self):
        return self.__radius * self.__radius * math.pi

    def getDiameter(self):
        return 2 * self.__radius

    def printCircle(self):
        print( "radius=" + str(self.__radius))
from CircleWithException import Circle


def main():
    try:
        c = Circle(10)
        print("c area is ",c.getArea())

        c1 = Circle(-1)
        print("c area is ",c1.getArea())

    except RuntimeError:
        print("Invalid radius")

main()

在这里插入图片描述

4.使用对象处理异常

def main():
    try:
        number=eval(input("Enter a number"))
        print("The number is",number)
    except NameError as ex:
        print( "Exception",ex)
main()

在这里插入图片描述

5.内置异常类

转载自:https://www.cnblogs.com/nmb-musen/
python:文件和异常处理_第5张图片

主要的是:

		ArithmeticError  
  		EnvironmentError--
  				OSError(errno, strerror[, filename[, winerror[, filename2]]])
此异常在一个系统函数返回系统相关的错误时将被引发,此类错误包括 I/O 操作失败例如 "文件未找到""磁盘已满" 等(不包括非法参数类型或其他偶然性错误)。
				--IOError
		RuntimeError                  
		LookupError 
		SyntaxError   

具体含义:

BaseException             所有异常的基类         
 +-- SystemExit              解释器请求退出
 +-- KeyboardInterrupt          用户中断执行(通常是输入^C)
 +-- GeneratorExit            生成器(generator)发生异常来通知退出
 +-- Exception               常规错误的基类
      +-- StopIteration              迭代器没有更多值 
      +-- StopAsyncIteration              必须通过异步迭代器对象的__anext__()方法引发以停止迭代
      +-- ArithmeticError                 所有数值计算错误的基类
      |    +-- FloatingPointError             浮点计算错误
      |    +-- OverflowError                  数值运算超出最大限制
      |    +-- ZeroDivisionError              除(或取模)(所有数据类型
      +-- AssertionError                  断言语句失败
      +-- AttributeError                  对象没有这个属性
      +-- BufferError                    与缓冲区相关的操作时引发
      +-- EOFError                        没有内建输入,到达EOF 标记
      +-- ImportError                     导入失败
      |    +-- ModuleNotFoundError        找不到模块
      +-- LookupError                     无效数据查询的基类
      |    +-- IndexError                      序列中没有此索引(index)
      |    +-- KeyError                        映射中没有这个键
      +-- MemoryError                     内存溢出错误
      +-- NameError                       未声明、初始化对象
      |    +-- UnboundLocalError              访问未初始化的本地变量
      +-- OSError                         操作系统错误,
      |    +-- BlockingIOError               操作将阻塞对象设置为非阻塞操作
      |    +-- ChildProcessError             子进程上的操作失败
      |    +-- ConnectionError               与连接相关的异常的基类
      |    |    +-- BrokenPipeError             在已关闭写入的套接字上写入
      |    |    +-- ConnectionAbortedError      连接尝试被对等方中止
      |    |    +-- ConnectionRefusedError      连接尝试被对等方拒绝
      |    |    +-- ConnectionResetError        连接由对等方重置
      |    +-- FileExistsError               创建已存在的文件或目录
      |    +-- FileNotFoundError             请求不存在的文件或目录
      |    +-- InterruptedError              系统调用被输入信号中断
      |    +-- IsADirectoryError             在目录上请求文件操作
      |    +-- NotADirectoryError            在不是目录的事物上请求目录操作
      |    +-- PermissionError              在没有访问权限的情况下运行操作
      |    +-- ProcessLookupError            进程不存在
      |    +-- TimeoutError                  系统函数在系统级别超时
      +-- ReferenceError                弱引用试图访问已经垃圾回收了的对象
      +-- RuntimeError                  一般的运行时错误
      |    +-- NotImplementedError      尚未实现的方法
      |    +-- RecursionError           解释器检测到超出最大递归深度
      +-- SyntaxError                   Python 语法错误
      |    +-- IndentationError         缩进错误
      |         +-- TabError          Tab 和空格混用
      +-- SystemError              一般的解释器系统错误
      +-- TypeError               对类型无效的操作
      +-- ValueError              传入无效的参数
      |    +-- UnicodeError             Unicode 相关的错误
      |         +-- UnicodeDecodeError     Unicode 解码时的错误
      |         +-- UnicodeEncodeError     Unicode 编码时错误
      |         +-- UnicodeTranslateError  Unicode 转换时错误
      +-- Warning                       警告的基类
           +-- DeprecationWarning          关于被弃用的特征的警告
           +-- PendingDeprecationWarning   关于构造将来语义会有改变的警告
           +-- RuntimeWarning           可疑的运行行为的警告
           +-- SyntaxWarning            可疑的语法的警告
           +-- UserWarning              用户代码生成的警告
           +-- FutureWarning            有关已弃用功能的警告的基类
           +-- ImportWarning            模块导入时可能出错的警告的基类
           +-- UnicodeWarning           与Unicode相关的警告的基类
           +-- BytesWarning             bytes和bytearray相关的警告的基类
           +-- ResourceWarning           与资源使用相关的警告的基类。。
​

6.自定义异常类

import math
class InvalidRadiusException(RuntimeError):
    def __init__(self,radius):
        super().__init__()
        self.radius=radius


class Circle:
    def __init__(self, radius):
        self.setRadius(radius)

    def getRadius(self):
        return self.__radius

    def setRadius(self, radius):
        if radius < 0:
           raise InvalidRadiusException(radius)  # 这里传错误的值给ex.radius
        else:
            self.__radius = radius

    def getArea(self):
        return self.__radius * self.__radius * math.pi

    def getDiameter(self):
        return 2 * self.__radius

    def printCircle(self):
        print( "radius=" + str(self.__radius))

def main():
    try:
        c1=Circle(5)
        print("c1 's area is",c1.getArea())

        c2=Circle(-5)
        print("c2 's area is ",c2.getArea())

    except InvalidRadiusException as ex:
        print("The raiuds" , ex.radius," is invalid.")

    except Exception:
        print("Something wrong exits")


main()

在这里插入图片描述

7.使用Pickling进行二进制的IO

import pickle
import os.path


# 保存到文件
def saveAddress():
    outfile = open(r"C:\Users\Lenovo\Desktop\addressBook.dat", "wb")
    addressList = input("Enter something to save").split()
    pickle.dump(addressList, outfile)
    outfile.close()


# 从文件中读取地地址对象列表
def loadAddressList():
    if not os.path.isfile(r"C:\Users\Lenovo\Desktop\addressBook.dat"):  # 先给定一个地址
        return []
    try:
        infile = open(r"C:\Users\Lenovo\Desktop\addressBook.dat", "rb")
        addressList = pickle.load(infile)
    except EOFError:
        return []
    infile.close()
    return addressList


def main():
    saveAddress()
    addressList = loadAddressList()
    for i in addressList:
        print(i, end=" ")


main()

核心代码:

pickle.dump(addressList, outfile)
addressList = pickle.load(infile)

7.2 实例 地址簿

import pickle
import os.path
from tkinter import *
import tkinter.messagebox


class Address:
    def __init__(self, name, street, city, state, zip):
        self.name = name
        self.street = street
        self.city = city
        self.state = state
        self.zip = zip


class AddressBook:
    def __init__(self):
        window = Tk()
        window.title("AddressBook")

        self.nameVar = StringVar()
        self.streetVar = StringVar()
        self.cityVar = StringVar()
        self.stateVar = StringVar()
        self.zipVar = StringVar()

        frame = Frame(window)
        frame.pack()
        Label(frame, text="Name").grid(row=1, column=1, sticky=W)
        Entry(frame, textvariable=self.nameVar, width=40).grid(row=1, column=2)

        frame1 = Frame(window)
        frame1.pack()
        Label(frame1, text="Street").grid(row=1, column=1, sticky=W)
        Entry(frame1, textvariable=self.streetVar, width=40).grid(row=1, column=2)

        frame2 = Frame(window)
        frame2.pack()
        Label(frame2, text="City").grid(row=1, column=1, sticky=W)
        Entry(frame2, textvariable=self.cityVar).grid(row=1, column=2)
        Label(frame2, text="State").grid(row=1, column=3)
        Entry(frame2, textvariable=self.stateVar, width=5).grid(row=1, column=4)
        Label(frame2, text="Zip").grid(row=1, column=5)
        Entry(frame2, textvariable=self.zipVar, width=6).grid(row=1, column=6)

        frame3 = Frame(window)
        frame3.pack()
        Button(frame3, text="Add", command=self.add).grid(row=1, column=1, sticky=W)
        Button(frame3, text="First", command=self.first).grid(row=1, column=2)
        Button(frame3, text="Next", command=self.next).grid(row=1, column=3)
        Button(frame3, text="Previous", command=self.previous).grid(row=1, column=4)
        Button(frame3, text="Last", command=self.last).grid(row=1, column=5)
        Button(frame3, text="delete", command=self.delete).grid(row=1, column=6)
        Button(frame3, text="Clear", command=self.clear).grid(row=1, column=7)
        self.addressList = self.loadAddressList()

        # 定义文件指针
        self.current = 0
        if len(self.addressList) > 0:
            self.setAddress()
        window.mainloop()

    def clear(self):
        self.nameVar.set(" ")
        self.streetVar.set(" ")
        self.cityVar.set(" ")
        self.stateVar.set(" ")
        self.zipVar.set(" ")

    # 从文件中读取地地址对象列表
    def loadAddressList(self):
        if not os.path.isfile(r"C:\Users\Lenovo\Desktop\addressBook.dat"):  # 先给定一个地址
            return []
        try:
            infile = open(r"C:\Users\Lenovo\Desktop\addressBook.dat", "rb")
            addressList = pickle.load(infile)
        except EOFError:
            return []
        infile.close()
        return addressList

    # 显示到窗口
    def setAddress(self):
        self.nameVar.set(self.addressList[self.current].name)
        self.streetVar.set(self.addressList[self.current].street)
        self.cityVar.set(self.addressList[self.current].city)
        self.stateVar.set(self.addressList[self.current].state)
        self.zipVar.set(self.addressList[self.current].zip)

    # 保存到文件
    def saveAddress(self):
        outfile = open(r"C:\Users\Lenovo\Desktop\addressBook.dat", "wb")
        pickle.dump(self.addressList, outfile)
        tkinter.messagebox.showinfo("Address saved", "A new address is saved")
        outfile.close()
        self.clear()

    # 增加
    def add(self):
        addressItem = Address(self.nameVar.get(), self.streetVar.get(),
                              self.cityVar.get(), self.stateVar.get(),
                              self.zipVar.get())
        self.addressList.append(addressItem)
        self.saveAddress()


    # 判空
    def isEmpty(self):
        return len(self.addressList) == 0

    # 第一个
    def first(self):
        if not self.isEmpty():
            self.current = 0
            self.setAddress()
        else:
            tkinter.messagebox.showwarning("Address empty", "no address is saved")

    # 下一个
    def next(self):
        if self.current < len(self.addressList) - 1:
            self.current += 1
            self.setAddress()
        else:
            tkinter.messagebox.showwarning("Address empty", "next address is unsaved")

    # 最后一个
    def last(self):
        if len(self.addressList) > 0:
            self.current = len(self.addressList) - 1
            self.setAddress()
        else:
            tkinter.messagebox.showwarning("Address empty", "no address is saved")

    # 前一个
    def previous(self):
        if self.current > 0:
            self.current -= 1
            self.setAddress()
        else:
            tkinter.messagebox.showwarning("Address empty", "no previous address is saved")

    def delete(self):
        if len(self.addressList) == 0:
            tkinter.messagebox.showwarning("Address empty", "no address is saved")
        elif len(self.addressList) == 1:
            self.addressList.pop()
            tkinter.messagebox.showinfo("Address deleted", "an address is deleted")
            self.clear()
        else:
            if self.current < len(self.addressList) - 1:
                self.next()
                self.addressList.pop(self.current - 1)
                tkinter.messagebox.showinfo("Address deleted", "an address is deleted")
            else:
                self.previous()
                self.addressList.pop()
                tkinter.messagebox.showinfo("Address deleted", "an address is deleted")


AddressBook()

python:文件和异常处理_第6张图片
在这里插入图片描述

8 、使用struct的pack,unpack进行二进制文件读写

import struct
# 参考于https://www.jianshu.com/p/5a985f29fa81

# # 按照给定的格式化字符串,把数据封装成字符串(实际上是类似于c结构体的字节流)
# string = struct.pack(fmt, v1, v2, ...)
#
# # 按照给定的格式(fmt)解析字节流string,返回解析出来的tuple
# tuple = unpack(fmt, string)
#
# # 计算给定的格式(fmt)占用多少字节的内存
# offset = calcsize(fmt)

def readFromTxt(fileName):
    inFile = open(fileName, "rb")
    line = inFile.read()
    realContext = struct.unpack('11s', line)
    print(realContext[0].decode("utf-8"))
    inFile.close()


def writeToTXT(fileName):
    outFile = open(fileName, "wb")
    buf = bytes("hello world".encode('utf-8'))
    bin_buf = struct.pack('11s', buf)
    outFile.write(bin_buf)
    outFile.close()


if __name__ == '__main__':
    writeToTXT(r"C:\Users\Lenovo\Desktop\hello.dat")
    readFromTxt(r"C:\Users\Lenovo\Desktop\hello.dat")

9、用二进制存储再读取求和

import pickle
import os.path


def saveAddress():
    outfile = open(r"C:\Users\Lenovo\Desktop\hello.dat", "wb")
    num = eval(input("Enter num:"))
    addressList = set()
    for i in range(num):
        addressList.add("".join(input("Enter number to save").split()))
    pickle.dump(addressList, outfile,2)
    outfile.close()


def loadAddressList():
    if not os.path.isfile(r"C:\Users\Lenovo\Desktop\hello.dat"):  # 先给定一个地址
        return {}
    try:
        infile = open(r"C:\Users\Lenovo\Desktop\hello.dat", "rb")
        addressList = pickle.load(infile)
    except EOFError:
        return {}
    infile.close()
    return addressList


def main():
    saveAddress()
    addressList = loadAddressList()
    sum = 0.0
    for i in range(len(addressList)):
        item = addressList.pop()
        sum += eval(item)
    print(sum)


main()

你可能感兴趣的:(python)