Last updated: 15 Jun 25 17:26:38 (UTC)

11.文件和异常

文件和异常

读取文件

先在同级目录创建pi_digits.txt 文件

3.1415926535
  8979323846
  2643383279
3.1415926535
  8979323846
  2643383279
from pathlib import Path

path = Path('pi_digits.txt')
contents = path.read_text()
print(contents)
from pathlib import Path

path = Path('pi_digits.txt')
contents = path.read_text()
print(contents)
3.1415926535
  8979323846
  2643383279
3.1415926535
  8979323846
  2643383279

相对路径

顾名思义,就是相对于你在使用的py文件的位置

我们可以通过dir命令在win系统看到我现在工作目录(即用vscode打开的文件夹)下有什么文件,工作目录下分别有main.pypi_digits.txt两个文件以及text_file__pycache__两个文件夹。其中text_file下还有一个1.txt文件。

PS E:\Documents\code> dir


    目录: E:\Documents\code


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----         2025/6/14     13:51                text_file     
d-----         2025/6/12     20:39                __pycache__   
-a----         2025/6/13     23:38           1481 main.py       
-a----         2025/6/14     13:36             40 pi_digits.txt 


PS E:\Documents\code> dir .\text_file\


    目录: E:\Documents\code\text_file


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----         2025/6/14     13:51              0 1.txt


PS E:\Documents\code> 
PS E:\Documents\code> dir


    目录: E:\Documents\code


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----         2025/6/14     13:51                text_file     
d-----         2025/6/12     20:39                __pycache__   
-a----         2025/6/13     23:38           1481 main.py       
-a----         2025/6/14     13:36             40 pi_digits.txt 


PS E:\Documents\code> dir .\text_file\


    目录: E:\Documents\code\text_file


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----         2025/6/14     13:51              0 1.txt


PS E:\Documents\code> 

创建一个指向1.txt文件的路径对象

path = Path('text_file/1.txt')
path = Path('text_file/1.txt')

绝对路径

无论py程序在哪一个目录,只要我们要读取的文件路径不变,py程序都能成功的执行的路径就是绝对路径

同样的我们创建一个指向1.txt文件的路径对象

 path = Path('E:/Documents/code/text_file/1.txt')
 path = Path('E:/Documents/code/text_file/1.txt')

访问特定某一行

将读取到的数据转换为列表,再通过索引访问某一行 注意: splitlines方法会自动去除掉最后一行的空换行

from pathlib import Path
path = Path('text_file/1.txt')
contents = path.read_text()
lines = contents.splitlines()
print(lines)
from pathlib import Path
path = Path('text_file/1.txt')
contents = path.read_text()
lines = contents.splitlines()
print(lines)

写入文件

这只展示一行的情况,多行的话添加\n就okay.

from pathlib import Path
path = Path('2.txt')
path.write_text('hello world')
from pathlib import Path
path = Path('2.txt')
path.write_text('hello world')

异常

一个程序往往是要让大量人同时运行的,难免有少部分人进行离谱的操作,造成程序异常。而我们知道py遇到一个报错往往会里面暂停程序,不会接着往下运行,这当然是不行的,因此我们要对异常进行处理。 有些异常是注定的,但它们不是bug,就比如ZeroDivisionError(一般就是拿0做分母)等,这类异常都是可预见的,可以提前解决的。

整数不能对0取模!

>>> 5 % 0
Traceback (most recent call last):
  File "<python-input-0>", line 1, in <module>
    5 % 0
    ~~^~~
ZeroDivisionError: integer modulo by zero
>>>
>>> 5 % 0
Traceback (most recent call last):
  File "<python-input-0>", line 1, in <module>
    5 % 0
    ~~^~~
ZeroDivisionError: integer modulo by zero
>>>
>>> try:
...     5 % 0
... except ZeroDivisionError:
...     '整数不能对0取模!'
...
'整数不能对0取模!'
>>> try:
...     5 % 0
... except ZeroDivisionError:
...     '整数不能对0取模!'
...
'整数不能对0取模!'

else

try-except后,如果要在try成功了才运行某些特定的代码,那就得使用else代码块了

>>> try:
...     5 % int(input('请输入数字'))
... except ZeroDivisionError:
...     '整数不能对0取模!'
... else:
...     '没有遇到可预见异常'
...

请输入数字2
1
'没有遇到可预见异常'
>>> try:
...     5 % int(input('请输入数字'))
... except ZeroDivisionError:
...     '整数不能对0取模!'
... else:
...     '没有遇到可预见异常'
...

请输入数字2
1
'没有遇到可预见异常'

存储/读取数据

path.exists()判断路径存不存在

json存储

字典、列表、字符串、数字、布尔、空值 可以直接转换为 json格式

from pathlib import Path
import json
num = [1,2,3,4,5]
path = Path('1.json')
contents = json.dumps(num)
path.write_text(contents,encoding = 'utf-8')
from pathlib import Path
import json
num = [1,2,3,4,5]
path = Path('1.json')
contents = json.dumps(num)
path.write_text(contents,encoding = 'utf-8')

json读取

from pathlib import Path
import json
path = Path('1.json')
contents = path.read_text(encoding='utf-8')
num = json.loads(contents)
print(num)
from pathlib import Path
import json
path = Path('1.json')
contents = path.read_text(encoding='utf-8')
num = json.loads(contents)
print(num)

简单的账号密码登记系统

三个类(n个方法),main.py负责调用/使用模块。 一个是存储/读取信息的类、一个是判断填入信息是否合规的类、最后一个是输入/输出信息处理的类 注意: 在方法前面添加__就能将方法私有化,只能在内部运行 出现中文乱码,那就看看是不是忘记在path的方法上加encoding='utf-8'json.dumps方法中的ensure_ascii参数值为False时才支持中文,否则会转码 而indent是对json内容进行格式化,让内容排版更有规律

# main.py
from account import *

def main():
    start = InputAccount()
    start.input_account()
try:
    main()
except BaseException as b:
    print(f'程序出错\n{b}')
# main.py
from account import *

def main():
    start = InputAccount()
    start.input_account()
try:
    main()
except BaseException as b:
    print(f'程序出错\n{b}')
# account.py
from pathlib import Path
import json
class AccountInfo:
    '''读取/保存账号信息'''
    def __init__(self, username, password):
        self.username = username
        self.password = password

    def __read_account(self):
        '''读取和处理账号信息'''
        path = Path('account.json')
        if path.exists():
            contents = path.read_text(encoding='utf-8')
            users_account = json.loads(contents)
            if users_account.get(self.username) == self.password:
                return (True,'read_success')
            else:
                return (False,'read_error')
        else:
            return (False, 'read_none')

    def __create_account(self):
        '''创建账号'''
        path = Path('account.json')
        if path.exists():
            contents = path.read_text(encoding='utf-8')
            users_account = json.loads(contents)
        else:
            users_account = {}
        if users_account.get(self.username):
            return (False, 'create_exist')
        else:
            users_account[self.username] = self.password
            contents = json.dumps(users_account, ensure_ascii = False, indent=4)
            path.write_text(contents, encoding='utf-8')
            return (True, 'create_success')

    def info_start(self, turn = 0):
        '''唯一的port以及处理通知'''
        msg = {
            'read_success': '✅ 登录成功',
            'read_error':'❌ 用户名或密码错误',
            'read_none':'❌ 账号文件不存在,请先创建账号',
            'create_exist':'❌ 用户名已存在,请选择其他用户名',
            'create_success':'✅ 账号创建成功'
        }
        if turn:
            result = self.__create_account()
        else:
            result = self.__read_account()
        print(msg[result[1]])

class AccountManager(AccountInfo):
    '''注册/登录账号'''
    def __init__(self, username, password):
        super().__init__(username, password)
    def __register(self):
        '''注册账号'''
        if self.username and self.password:
            self.info_start(turn = 1)
            return (True, 'sign_success')
        else:
            return (False, 'none')
    def __login(self):
        '''登录账号'''
        if self.username and self.password:
            self.info_start()
            return (True, 'login_success')
        else:
            return (False, 'none')
    def am_start(self, turn = 0):
        '''唯一port以及处理通知'''
        msg = {
        'sign_success': '',
        'none':'❌ 用户名或密码不能为空',
        'login_success':''
        }
        if turn:
            result = self.__register()
        else:
            result = self.__login()
        if msg[result[1]]:
            print(msg[result[1]])

class InputAccount:
    '''输入账号信息'''
    def __init__(self):
        self.username = ""
        self.password = ""

    def input_account(self):
        print("欢迎使用账号管理系统")
        action = input("请选择操作: 1. 注册 2. 登录\n")
        def input_info():
            self.username = input('请输入用户名: ')
            self.password = input('请输入密码: ')
            AccountManager(self.username, self.password).am_start(action)

        if action == '1':
            input_info()
        elif action == '2':
            action = 0
            input_info()
        else:
            print("无效的操作,请重新选择。")


if __name__ == "__main__":
    # 测试代码
    pass
# account.py
from pathlib import Path
import json
class AccountInfo:
    '''读取/保存账号信息'''
    def __init__(self, username, password):
        self.username = username
        self.password = password

    def __read_account(self):
        '''读取和处理账号信息'''
        path = Path('account.json')
        if path.exists():
            contents = path.read_text(encoding='utf-8')
            users_account = json.loads(contents)
            if users_account.get(self.username) == self.password:
                return (True,'read_success')
            else:
                return (False,'read_error')
        else:
            return (False, 'read_none')

    def __create_account(self):
        '''创建账号'''
        path = Path('account.json')
        if path.exists():
            contents = path.read_text(encoding='utf-8')
            users_account = json.loads(contents)
        else:
            users_account = {}
        if users_account.get(self.username):
            return (False, 'create_exist')
        else:
            users_account[self.username] = self.password
            contents = json.dumps(users_account, ensure_ascii = False, indent=4)
            path.write_text(contents, encoding='utf-8')
            return (True, 'create_success')

    def info_start(self, turn = 0):
        '''唯一的port以及处理通知'''
        msg = {
            'read_success': '✅ 登录成功',
            'read_error':'❌ 用户名或密码错误',
            'read_none':'❌ 账号文件不存在,请先创建账号',
            'create_exist':'❌ 用户名已存在,请选择其他用户名',
            'create_success':'✅ 账号创建成功'
        }
        if turn:
            result = self.__create_account()
        else:
            result = self.__read_account()
        print(msg[result[1]])

class AccountManager(AccountInfo):
    '''注册/登录账号'''
    def __init__(self, username, password):
        super().__init__(username, password)
    def __register(self):
        '''注册账号'''
        if self.username and self.password:
            self.info_start(turn = 1)
            return (True, 'sign_success')
        else:
            return (False, 'none')
    def __login(self):
        '''登录账号'''
        if self.username and self.password:
            self.info_start()
            return (True, 'login_success')
        else:
            return (False, 'none')
    def am_start(self, turn = 0):
        '''唯一port以及处理通知'''
        msg = {
        'sign_success': '',
        'none':'❌ 用户名或密码不能为空',
        'login_success':''
        }
        if turn:
            result = self.__register()
        else:
            result = self.__login()
        if msg[result[1]]:
            print(msg[result[1]])

class InputAccount:
    '''输入账号信息'''
    def __init__(self):
        self.username = ""
        self.password = ""

    def input_account(self):
        print("欢迎使用账号管理系统")
        action = input("请选择操作: 1. 注册 2. 登录\n")
        def input_info():
            self.username = input('请输入用户名: ')
            self.password = input('请输入密码: ')
            AccountManager(self.username, self.password).am_start(action)

        if action == '1':
            input_info()
        elif action == '2':
            action = 0
            input_info()
        else:
            print("无效的操作,请重新选择。")


if __name__ == "__main__":
    # 测试代码
    pass