【零基础学Python】06-Python模块和包、异常处理、文件常用操作

✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨

🎯 你正在阅读「Python 从零摸索日记」系列文章 🎯

✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨

🔥 弹简特 个人主页

❄️ 个人专栏直通车:

靠热爱去书写自己,靠勇敢去书写生活!

✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨


🌟 博主简介:


文章目录:


一、前言

老铁们,本文带你理清模块、包、库的层级关系,掌握导入技巧、异常捕获与文件操作。从零实战,轻松跨越新手进阶门槛。


二、模块、包、库

1、概念

1.1 模块

一句话解释

一个 .py 文件就是一个模块。模块里可以写变量、函数、类等。

生活类比

模块就像一本"菜谱"的其中一页。这一页专门记录"鱼香肉丝"的做法(变量、函数、类等)。

例子

你新建一个文件叫 tools.py,里面写:

python 复制代码
# tools.py 这个文件就是一个模块
name = "计算器"

def add(a, b):
    return a + b

def multiply(a, b):
    return a * b

这个 tools.py 就是一个模块。

1.2 包

一句话解释

一个包含多个 .py 模块的文件夹,并且这个文件夹里必须有一个 __init__.py 文件(可以是空的),这个文件夹就叫做包。

生活类比

包就像一个"菜谱文件夹",里面有好多页(模块),每页一个菜。__init__.py 就像文件夹的封面,标记这是一个包。

例子

bash 复制代码
my_package/          # 这是一个包(文件夹)
    __init__.py      # 必须存在(可以是空文件)
    math_tools.py    # 模块1
    string_tools.py  # 模块2

1.3 库

一句话解释

库是一个更大的概念,通常指多个包集合在一起 ,提供一系列相关功能。比如 Python 标准库(ossysrandom 等)、第三方库(requestsnumpypandas)。

生活类比

库就像一个"大图书馆",里面有好多菜谱文件夹(包),还有很多其他功能的书。

注意

在口语中,可能很多人会把"模块"、"包"、"库"混用,但我们得要知道它们层级关系:

模块(一个文件) < 包(一个文件夹+多个文件) < 库(多个包)


2、导入模块的常用方式

Python 有很多自带的模块(标准库),不需要安装,直接 import 就能用。

2.1 方式1:import 模块名

使用格式:模块名.函数名()模块名.变量名

例子 :使用 random 模块生成随机数

python 复制代码
import random

num = random.randint(1, 10)  # 生成1到10之间的随机整数
print(num)

2.2 方式2:from 模块名 import 函数名/变量名

这样导入后,可以直接用函数名,不需要加模块名前缀。

python 复制代码
from random import randint

num = randint(1, 10)   # 直接写函数名
print(num)

导入多个方法或者变量from random import randint, choice, shuffle

2.3 方式3:from 模块名 import *

导入模块中的所有内容(不推荐,容易命名冲突)。

python 复制代码
from random import *

num = randint(1, 10)
print(choice(["苹果", "香蕉"]))

2.4 给模块或函数起别名(as

当模块名太长,或者你自己想换个名字,用 as 取别名。

python 复制代码
import random as r

num = r.randint(1, 10)   # 用别名 r
print(num)

也可以给函数起别名:

python 复制代码
from random import randint as ri

num = ri(1, 10)
print(num)

注意 :原名 randint 失效,只能用新名字 ri


3、自定义模块的创建和导入

3.1 创建自定义模块

假设在当前目录下新建一个文件 mymodule.py,里面写:

python 复制代码
# mymodule.py
name = "张三"

def say_hello():
    print("你好,我是自定义模块的函数")

3.2 导入自定义模块

在同一目录下新建一个文件 main.py,然后导入 mymodule

方式1:import 模块名

python 复制代码
import mymodule

print(mymodule.name)    # 输出:张三
mymodule.say_hello()    # 输出:你好,我是自定义模块的函数

方式2:from 模块名 import 变量/函数

python 复制代码
from mymodule import name, say_hello

print(name)          # 直接使用变量
say_hello()          # 直接调用函数

方式3:from 模块名 import *

python 复制代码
from mymodule import *

print(name)
say_hello()

注意:Python 导入模块时,会执行模块中的代码(比如打印语句、定义函数等)。但一般模块里只放定义,不放主动执行的代码(除了测试)。


4、自定义包的创建和导入

4.1 创建包的结构

假设我们想创建一个包叫 mypackage,里面有两个模块:module_a.pymodule_b.py

步骤:

  1. 新建一个文件夹,叫 mypackage
  2. 在文件夹里新建一个空文件 __init__.py(Python 识别包必须要有这个文件,可以是空的)。
  3. 在文件夹里新建 module_a.pymodule_b.py

文件夹结构:

bash 复制代码
当前目录/
├── main.py                # 我们用来测试导入的文件
└── mypackage/             # 这是一个包
    ├── __init__.py        # 空文件
    ├── module_a.py
    └── module_b.py

module_a.py 内容:

python 复制代码
# module_a.py
name_a = "模块A"
def func_a():
    print("我是模块A的函数")

module_b.py 内容:

python 复制代码
# module_b.py
name_b = "模块B"
def func_b():
    print("我是模块B的函数")

4.2 导入包中的模块

main.py 中,你可以用以下几种方式导入:

方式1:导入整个模块(需要加包名.模块名)

python 复制代码
import mypackage.module_a

print(mypackage.module_a.name_a)
mypackage.module_a.func_a()

方式2:from 包名 import 模块名

python 复制代码
from mypackage import module_a

print(module_a.name_a)
module_a.func_a()

方式3:from 包名.模块名 import 具体内容

python 复制代码
from mypackage.module_a import name_a, func_a

print(name_a)
func_a()

方式4:from 包名.模块名 import *

python 复制代码
from mypackage.module_a import *

print(name_a)
func_a()

4.3 关于 __init__.py 的作用

__init__.py。它的作用:

  • 告诉 Python 这个文件夹是一个包,可以被导入。
  • 可以在里面写代码,当你 import mypackage 时会自动执行。
  • 可以控制 from mypackage import * 会导入哪些模块(通过定义 __all__ 列表)。

通常我们初学者可以暂时只放一个空文件。


5、注意事项和常见错误

5.1 命名规则

模块名、包名、变量名、函数名都要符合标识符命名规则:

字母、数字、下划线组成,不能数字开头,不能是关键字(如 ifforimport),区分大小写。

5.2 导入路径问题

Python 查找模块的路径包括:

  • 当前脚本所在目录
  • 环境变量 PYTHONPATH
  • 标准库路径
  • 第三方库安装路径

如果自定义模块不在当前目录,需要添加路径或用相对导入(以后讲)。

5.3 循环导入

不要出现 a.py 导入 b.py,同时 b.py 又导入 a.py,会导致错误。

例如:

5.4 importfrom ... import ... 的区别

  • import 模块名:需要写 模块名.xxx,不会污染当前命名空间。
  • from 模块名 import xxx:直接使用 xxx,但如果有同名变量会覆盖。

推荐:一般用 import 模块名 更清晰;只导入少数常用函数时可以用 from ... import ...


三、异常处理

1、什么是异常?

一句话解释

你写的代码在运行时发生了错误(比如变量没定义、除以零、文件不存在),Python 就会"抛出一个异常",程序会崩溃并打印一堆红色错误信息。

生活类比

你让朋友去拿"冰箱里的蛋糕",但冰箱里根本没有蛋糕。朋友就会回来跟你说"没有蛋糕啊!"------这个"没有蛋糕"就是异常。

最简单的异常例子

python 复制代码
print(a)   # a 这个变量没定义过

运行后你会看到类似这样的信息:

  • Traceback:异常追溯,告诉你错误发生的路径。
  • File "xxx", line 1:哪个文件的第几行。
  • NameError: name 'a' is not defined:异常类型和具体原因。

这些异常信息构造 就是告诉你:异常信息包括执行路径文件行号错误类型和原因。看懂这些信息就能快速定位 bug。


2、怎么捕获异常?(try-except-else-finally)

如果你的程序可能因为用户输入错误、文件不存在等发生异常,你不想让程序崩溃 ,而是想"优雅地处理"这个错误(比如提示用户重新输入),这时就用 try...except

基本结构

python 复制代码
try:
    # 这里放可能会出错的代码
except:
    # 如果 try 中出了异常,就执行这里的代码(程序不会崩溃)
else:
    # 如果 try 中没有出异常,就执行这里的代码(可选)
finally:
    # 不管有没有异常,最后都会执行这里的代码(可选,常用于关闭文件、释放资源)

例如

python 复制代码
try:
    print("开始尝试执行代码")
    num = int(input("请输入一个数字:"))   # 如果用户输入的不是数字,会触发 ValueError
    result = 10 / num                     # 如果用户输入 0,会触发 ZeroDivisionError
    print("计算结果是:", result)
except:
    print("出错了!可能是输入的不是数字,或者除以了零。")
else:
    print("没有发生异常,恭喜!")
finally:
    print("不管有没有异常,我都会执行。")

执行情况模拟

  • 用户输入 5(正常)→ 输出:

    复制代码
    开始尝试执行代码
    计算结果是: 2.0
    没有发生异常,恭喜!
    不管有没有异常,我都会执行。
  • 用户输入 0(除以零)→ 输出:

    复制代码
    开始尝试执行代码
    出错了!可能是输入的不是数字,或者除以了零。
    不管有没有异常,我都会执行。
  • 用户输入 abc(不是数字)→ 输出类似上面。

关键点

  • try 中一旦发生异常,立刻跳转到 excepttry 中剩余代码不再执行。
  • except 只捕获异常,不解决异常根源(只是让你有机会做补救措施,比如提示重新输入)。
  • else 只有在 try 完全没异常时才执行。
  • finally 无论如何都执行,非常适合做清理工作(比如关闭文件)。

3、捕获特定类型的异常

上面的 except: 会捕获所有 异常,但有时候你想针对不同异常做不同处理,可以写多个 except

python 复制代码
try:
    num = int(input("输入数字:"))
    result = 10 / num
except ValueError:
    print("你输入的不是合法数字!")
except ZeroDivisionError:
    print("不能除以零!")
except Exception as e:   # 捕获其他所有异常,e 是异常对象
    print("未知错误:", e)
else:
    print("结果是", result)
finally:
    print("结束")

建议 :写代码时先不要加 try,先让程序崩溃,看清楚是什么异常类型(比如 ValueErrorZeroDivisionError),然后再用对应的 except 去捕获它。


4、异常的传递

一句话解释

如果函数 A 调用函数 B,函数 B 调用函数 C,在 C 中发生了异常且没有捕获,那么这个异常会一层一层往外传 ,直到被某个 try...except 捕获,如果一直没捕获,程序就崩溃。

例子

python 复制代码
def func1():
    print("func1 开始")
    func2()   # 调用 func2

def func2():
    print("func2 开始")
    print(x)   # x 没定义,会触发 NameError

def main():
    try:
        func1()
    except NameError:
        print("捕获到了 NameError,程序没有崩溃")

main()

输出:

复制代码
func1 开始
func2 开始
捕获到了 NameError,程序没有崩溃

关键点

  • 异常会沿着调用链往回传递,直到被 try...except 接住。
  • 如果最外层也没接,程序就崩溃并打印 Traceback(那个红色错误信息)。
  • 利用这个特性,你可以在合适的地方统一处理异常 ,而不是每个函数内部都写 try

四、文件操作

1、操作文件的三个步骤

  1. 打开文件open(文件路径, 模式, encoding='编码')
  2. 读/写文件.read().write().readlines()
  3. 关闭文件.close()(释放系统资源)

生活类比

打开冰箱(打开文件),拿一瓶饮料(读或写),关上冰箱门(关闭文件)。不关门的话,冰箱会一直耗电(占用系统资源)。


2、文件的打开模式

模式 含义 文件不存在时
'r' 只读(默认) 报错 FileNotFoundError
'w' 只写,会覆盖原有内容 创建新文件
'a' 追加,在文件末尾写入 创建新文件
'rb' 二进制只读(图片、视频等) 报错
'wb' 二进制只写,会覆盖 创建新文件
'ab' 二进制追加 创建新文件

注意 :文本文件(.txt)一般指定 encoding='utf-8',二进制文件(图片、音频)不能 指定 encoding


3、读取文件内容(read, readlines, readline

假设有一个 test.txt 文件,内容为:

复制代码
你好,这里是
零基础学Python园地

方法1:.read() --- 一次性读取全部内容(字符串)

python 复制代码
file = open('text.txt', 'r', encoding='utf-8')
content = file.read()
print(content)   # 输出两行文字
file.close()

方法2:.readlines() --- 一次性读取全部,按行返回列表(每行末尾有 \n

python 复制代码
file = open('text.txt', 'r', encoding='utf-8')
lines = file.readlines()
print(lines) # 输出:['你好,这里是\n', '零基础学Python园地']
# 去除换行符
print('--'*100)
# 首先使用一个列表,到时候存储去除换行之后的数据
clean_lines = []
# 遍历返回的lines
for i in lines:
    clean_lines.append(i.strip())
print(clean_lines) # 输出:['你好,这里是', '零基础学Python园地']
file.close()

方法3:.readline() --- 一次读取一行,多次调用读取下一行

python 复制代码
file = open('text.txt', 'r', encoding='utf-8')
line1 = file.readline()   # 第一行
line2 = file.readline()   # 第二行
print(line1, end='')      # 不额外加换行
print(line2, end='')
file.close()

注意.read().readlines() 适合小文件;大文件建议用循环 .readline() 或直接 for line in file:


4、写入文件(w 覆盖,a 追加)

覆盖写入 ('w')

文件存在则清空原内容,不存在则新建。

python 复制代码
file = open('output.txt', 'w', encoding='utf-8')
file.write("第一行\n")      # \n 表示换行
file.write("第二行")
file.close()

追加写入 ('a')

在文件末尾追加内容,不覆盖原有内容。

python 复制代码
file = open('output.txt', 'a', encoding='utf-8')
file.write("\n新增的一行")
file.close()

5、二进制文件操作(图片、音频等)

不能直接 'r''w' 去读写图片,因为图片是二进制数据。要用 'rb'(读二进制)和 'wb'(写二进制)。

例子:复制图片

接下来使用文件的读取加写入,将这个文件拷贝一份到output目录下,注意前提得先有output这个目录

代码如下:

python 复制代码
# 打开原图(二进制读)
# 打开原图(二进制读)
with open('srcpic/1.jpg', 'rb') as src:
    data = src.read()

# 写入新文件(二进制写)
with open('output/1_copy.jpg', 'wb') as dst:
    dst.write(data)

解释疑问: 为什么第二个中可以使用第一个的局部变量?

只有函数、类、模块才会创建新的作用域 。像 with、if、for、while 这些语句块,不会创建独立的作用域

所以,你在第一个 with 块里定义的变量 data,其实是属于它所在的函数或全局作用域。第二个 with 块自然也能访问到它。

结果:

什么是 with open(...) as 变量:

这叫"上下文管理器",它会在代码块执行完后自动关闭文件 ,即使中间发生异常也会关闭。你就不需要手动写 .close() 了,非常推荐使用。

用法

python 复制代码
with open('rap.txt', 'r', encoding='utf-8') as f:
    content = f.read()
# 这里文件已经自动关闭,不需要 f.close()

6、文件常用操作(删除文件、删除文件夹)

需要导入 osshutil 模块。

  • 删除文件os.remove('文件路径')
  • 删除空文件夹os.rmdir('文件夹路径')(只能删空的)
  • 删除非空文件夹(递归删除,慎用!)shutil.rmtree('文件夹路径')
python 复制代码
import os
import shutil

# 删除单个文件
os.remove('test.txt')

# 删除空文件夹
os.rmdir('empty_folder')

# 删除非空文件夹(危险,删了找不回)
shutil.rmtree('not_empty_folder')

注意shutil.rmtree 非常危险,没有回收站功能,生产环境慎用。


6.1 删除文件

使用:os.remove(文件目录)

py 复制代码
# 文件的删除
import os
os.remove('output.txt')

6.2 删除文件夹

py 复制代码
# 删除文件夹

import os
import shutil
# 删除一个空的文件夹使用的是rmdir
os.rmdir('111')
# 删除一个非空的文件夹使用 rmtree
shutil.rmtree('output')

6.3 获取指定目录文件列表

使用:os.listdir(目录)

py 复制代码
import os
# 获取指定的目录文件列表
list_dir = os.listdir(r"E:\python_project\basic-python-grammar-learning\PythonBasicGrammar")
# 返回的是列表
print(list_dir)
print(f'列表中每一个元素是字符串:{type(list_dir[0])}')

如果路径中出现了转义字符,那么我们就在字符串前面加一个r

6.4 修改文件名和文件

py 复制代码
import os
# 修改文件名
os.rename('tools.py', 'tool.py')
# 修改目录名
os.rename('srcpic', 'des')

6.5 获取当前文件的路径信息

py 复制代码
# 获取当前文件的路径信息:绝对路径
import os
print(os.getcwd())

6.6 创建一个文件夹

py 复制代码
# 创建一个文件夹
import os
os.mkdir('111')

五、写在最后

能坚持看到最后的朋友,属实是真爱学编程了,先歇会儿眼睛放松一下~

很多同学刚开始学Python,都不知道它到底能干啥。还是简单跟大伙唠唠:

可以做自动化测试 、写办公脚本解放双手爬虫采集数据做数据分析、开发小工具、甚至做简单后端和小游戏,用途真的特别广。

最后分享几句实在又走心的话送给正在学Python的你:

  1. 慢慢来别着急,代码不会辜负每一个愿意坚持敲键盘的人

  2. 现在多学一点技能,未来就多一份选择的底气

  3. 与其原地迷茫焦虑,不如从一行Python代码开始悄悄变强

  4. 看似不起眼的日复一日,终会在将来的某天,让你看到坚持的意义

铁汁们~ 觉得内容有用的话,麻烦点个赞、关注一波,后续会持续更新Python入门、实战、自动化相关笔记,咱们一起慢慢进阶。

文章有哪里讲得不妥的,欢迎评论区随时指正,大家一起交流进步!

兄弟们,咱们一起学好Python,悄悄逆袭~~~

相关推荐
x***r1511 小时前
Postman-win64-7.2.2-Setup安装步骤详解(附API接口测试与参数配置教程)
开发语言·lua
念恒123061 小时前
Python 面向对象编程核心:对象、实例化、封装与变量作用域
开发语言·python
薛定谔的悦1 小时前
光伏-储能-负荷联合预测:给 EMS 装上“预知能力“
java·数据库·人工智能·python·储能
大菜菜小个子1 小时前
template<typename T>使用
java·开发语言·算法
L_09071 小时前
【C++】C++11 新特性
开发语言·c++
方也_arkling1 小时前
【Java-Day15】API篇-ArrayList集合
java·开发语言
我是一颗柠檬2 小时前
【Java后端技术亮点】动态路由权限(按钮级权限),细粒度控制到按钮级别
java·开发语言·后端·状态模式
Fanfanaas2 小时前
C++ 继承
java·开发语言·jvm·c++·学习·算法
在繁华处2 小时前
Java从零到熟练(十一):Spring框架入门
java·开发语言·spring