Python进阶

2024-07-06  
0条评论   112浏览

异常处理

try/except

while True:
    try:
        x = int(input("请输入一个数字: "))
        break
    except ValueError:
        print("您输入的不是数字,请再次尝试输入!")

try 语句按照如下方式工作;

  • 首先,执行 try 子句(在关键字 try 和关键字 except 之间的语句)。
  • 如果没有异常发生,忽略 except 子句,try 子句执行后结束。
  • 如果在执行 try 子句的过程中发生了异常,那么 try 子句余下的部分将被忽略。如果异常的类型和 except 之后的名称相符,那么对应的 except 子句将被执行。
  • 如果一个异常没有与任何的 except 匹配,那么这个异常将会传递给上层的 try 中。

一个 try 语句可能包含多个except子句,分别来处理不同的特定的异常。最多只有一个分支会被执行。

处理程序将只针对对应的 try 子句中的异常进行处理,而不是其他的 try 的处理程序中的异常。

一个except子句可以同时处理多个异常,这些异常将被放在一个括号里成为一个元组,例如:

except (RuntimeError, TypeError, NameError):
    pass

最后一个except子句可以忽略异常的名称,它将被当作通配符使用。你可以使用这种方法打印一个错误信息,然后再次把异常抛出。

import sys

try:
    f = open('myfile.txt')
    s = f.readline()
    i = int(s.strip())
except OSError as err:
    print("OS error: {0}".format(err))
except ValueError:
    print("Could not convert data to an integer.")
except:
    print("Unexpected error:", sys.exc_info()[0])
    raise

try/except...else

try/except 语句还有一个可选的 else 子句,如果使用这个子句,那么必须放在所有的 except 子句之后。

else 子句将在 try 子句没有发生任何异常的时候执行。

以下实例在 try 语句中判断文件是否可以打开,如果打开文件时正常的没有发生异常则执行 else 部分的语句,读取文件内容:

import sys
for arg in sys.argv[1:]:
    try:
        f = open(arg, 'r')
    except IOError:
        print('cannot open', arg)
    else:
        print(arg, 'has', len(f.readlines()), 'lines')
        f.close()

try-finally 语句

try-finally 语句无论是否发生异常都将执行最后的代码。

try:
    print("a")
except AssertionError as error:
    print(error)
else:
    try:
        with open('file.log') as file:
            read_data = file.read()
    except FileNotFoundError as fnf_error:
        print(fnf_error)
finally:
    print('这句话,无论异常是否发生都会执行。')

抛出异常

Python 使用 raise 语句抛出一个指定的异常。

raise语法格式如下:

raise [Exception [, args [, traceback]]]
#案例
x = 10
if x > 5:
    raise Exception('x 不能大于 5。x 的值为: {}'.format(x))

raise 唯一的一个参数指定了要被抛出的异常。它必须是一个异常的实例或者是异常的类(也就是 Exception 的子类)。

如果你只想知道这是否抛出了一个异常,并不想去处理它,那么一个简单的 raise 语句就可以再次把它抛出。

try:
    raise NameError('HiThere')  # 模拟一个异常。
except NameError:
    print('An exception flew by!')
    raise

用户自定义异常

你可以通过创建一个新的异常类来拥有自己的异常。异常类继承自 Exception 类,可以直接继承,或者间接继承。

class MyError(Exception):
    def __init__(self, value):
        self.value = value
        print("init")

    def __str__(self):
        print("str")
        return repr(self.value)

try:
    raise MyError(2 * 2)
except MyError as e:
    print('My exception occurred, value:', e.value)

raise MyError('oops!')

#结果
init
My exception occurred, value: 4
init
str
Traceback (most recent call last):
  File "E:\Python\project\Base01\test01.py", line 15, in <module>
    raise MyError('oops!')
MyError: 'oops!'

在这个例子中,类 Exception 默认的 init() 被覆盖。

当创建一个模块有可能抛出多种不同的异常时,一种通常的做法是为这个包建立一个基础异常类,然后基于这个基础类为不同的错误情况创建不同的子类:

class Error(Exception):
    """Base class for exceptions in this module."""
    pass

class InputError(Error):
    """Exception raised for errors in the input.

    Attributes:
        expression -- input expression in which the error occurred
        message -- explanation of the error
    """

    def __init__(self, expression, message):
        self.expression = expression
        self.message = message

class TransitionError(Error):
    """Raised when an operation attempts a state transition that's not
    allowed.

    Attributes:
        previous -- state at beginning of transition
        next -- attempted new state
        message -- explanation of why the specific transition is not allowed
    """

    def __init__(self, previous, next, message):
        self.previous = previous
        self.next = next
        self.message = message

with 关键字

Python 中的 with 语句用于异常处理,封装了 try…except…finally 编码范式,提高了易用性。

with 语句使代码更清晰、更具可读性, 它简化了文件流等公共资源的管理。

在处理文件对象时使用 with 关键字是一种很好的做法。

我们可以看下以下几种代码实例:

不使用 with,也不使用 try…except…finally

file = open('./test_runoob.txt', 'w')
file.write('hello world !')
file.close()

以上代码如果在调用 write 的过程中,出现了异常,则 close 方法将无法被执行,因此资源就会一直被该程序占用而无法被释放。 接下来我们呢可以使用 try…except…finally 来改进代码:

file = open('./test_runoob.txt', 'w')
try:
    file.write('hello world')
finally:
    file.close()

以上代码我们对可能发生异常的代码处进行 try 捕获,发生异常时执行 except 代码块,finally 代码块是无论什么情况都会执行,所以文件会被关闭,不会因为执行异常而占用资源。

使用 with 关键字:

with open('./test_runoob.txt', 'w') as file:
    file.write('hello world !')

使用 with 关键字系统会自动调用 f.close() 方法, with 的作用等效于 try/finally 语句是一样的。

我们可以在执行 with 关键字后检验文件是否关闭:

with open('./test_runoob.txt') as f:
	read_data = f.read()

with 语句实现原理建立在上下文管理器之上。

上下文管理器是一个实现 enterexit 方法的类。

使用 with 语句确保在嵌套块的末尾调用 exit 方法。

这个概念类似于 try...finally 块的使用。

with open('./test_runoob.txt', 'w') as my_file:
    my_file.write('hello world!')

以上实例将 hello world! 写到 ./test_runoob.txt 文件上。

在文件对象中定义了 enterexit 方法,即文件对象也实现了上下文管理器,首先调用 enter 方法,然后执行 with 语句中的代码,最后调用 exit 方法。 即使出现错误,也会调用 exit 方法,也就是会关闭文件流。

推导式

列表(list)推导式

列表推导式格式为:

[表达式 for 变量 in 列表] 
[out_exp_res for out_exp in input_list]

或者 

[表达式 for 变量 in 列表 if 条件]
[out_exp_res for out_exp in input_list if condition]
  • out_exp_res:列表生成元素表达式,可以是有返回值的函数。
  • for out_exp in input_list:迭代 input_list 将 out_exp 传入到 out_exp_res 表达式中。
  • if condition:条件语句,可以过滤列表中不符合条件的值。

案例

names = ['Bob', 'Tom', 'alice', 'Jerry', 'Wendy', 'Smith']
new_names = [name.upper() for name in names if len(name) > 3]
print(new_names)
['ALICE', 'JERRY', 'WENDY', 'SMITH']

元组(tuple)推导式

元组推导式可以利用 range 区间、元组、列表、字典和集合等数据类型,快速生成一个满足指定需求的元组。

元组推导式基本格式:

(expression for item in Sequence )
或
(expression for item in Sequence if conditional )

案例

a = (x for x in range(1, 10))
x=tuple(a)
print(x)

集合(set)推导式

集合推导式基本格式:

{ expression for item in Sequence }
或
{ expression for item in Sequence if conditional }

案例

setnew = {i ** 2 for i in (1, 2, 3)}
print(setnew)

字典(dict)推导式

字典推导基本格式:

{ key_expr: value_expr for value in collection }

或

{ key_expr: value_expr for value in collection if condition }

案例

listdemo = ['Google', 'Runoob', 'Taobao']
# 将列表中各字符串值为键,各字符串的长度为值,组成键值对
newdict = {key: len(key) for key in listdemo}

迭代器与生成器

迭代器

迭代是 Python 最强大的功能之一,是访问集合元素的一种方式。

迭代器是一个可以记住遍历的位置的对象。

迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。

字符串,列表或元组对象都可用于创建迭代器

方法

迭代器有两个基本的方法:iter()next()

StopIteration

StopIteration 异常用于标识迭代的完成,防止出现无限循环的情况,在 next() 方法中我们可以设置在完成指定循环次数后触发 StopIteration 异常来结束迭代。

基本案例

list = [1, 2, 3, 4]
it = iter(list)  # 创建迭代器对象
print(next(it))  # 输出迭代器的下一个元素
print(next(it))
import sys  # 引入 sys 模块

list = [1, 2, 3, 4]
it = iter(list)  # 创建迭代器对象

while True:
    try:
        print(next(it))
    except StopIteration:
        sys.exit()

生成器

在 Python 中,使用了 yield 的函数被称为生成器(generator)。

yield 是一个关键字,用于定义生成器函数,生成器函数是一种特殊的函数,可以在迭代过程中逐步产生值,而不是一次性返回所有结果。

跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。

当在生成器函数中使用 yield 语句时,函数的执行将会暂停,并将 yield 后面的表达式作为当前迭代的值返回。

然后,每次调用生成器的 next() 方法或使用 for 循环进行迭代时,函数会从上次暂停的地方继续执行,直到再次遇到 yield 语句。这样,生成器函数可以逐步产生值,而不需要一次性计算并返回所有结果。

调用一个生成器函数,返回的是一个迭代器对象。

def countdown(n):
    while n > 0:
        yield n
        n -= 1


# 创建生成器对象
generator = countdown(5)

# 通过迭代生成器获取值
print(next(generator))  # 输出: 5
print(next(generator))  # 输出: 4
print(next(generator))  # 输出: 3

# 使用 for 循环迭代生成器
for value in generator:
    print(value)  # 输出: 2 1

以上实例中,countdown 函数是一个生成器函数。它使用 yield 语句逐步产生从 n 到 1 的倒数数字。在每次调用 yield 语句时,函数会返回当前的倒数值,并在下一次调用时从上次暂停的地方继续执行。

通过创建生成器对象并使用 next() 函数或 for 循环迭代生成器,我们可以逐步获取生成器函数产生的值。在这个例子中,我们首先使用 next() 函数获取前三个倒数值,然后通过 for 循环获取剩下的两个倒数值。

生成器函数的优势是它们可以按需生成值,避免一次性生成大量数据并占用大量内存。此外,生成器还可以与其他迭代工具(如for循环)无缝配合使用,提供简洁和高效的迭代方式。

import sys

def fibonacci(n):  # 生成器函数 - 斐波那契
    a, b, counter = 0, 1, 0
    while True:
        if (counter > n):
            return
        yield a
        a, b = b, a + b
        counter += 1

f = fibonacci(10)  # f 是一个迭代器,由生成器返回生成

while True:
    try:
        print(next(f), end=" ")
    except StopIteration:
        sys.exit()

装饰器

装饰器(decorators)是 Python 中的一种高级功能,它允许你动态地修改函数或类的行为。

装饰器是一种函数,它接受一个函数作为参数,并返回一个新的函数或修改原来的函数。

装饰器的语法使用 @decorator_name 来应用在函数或方法上。

Python 还提供了一些内置的装饰器,比如 @staticmethod@classmethod,用于定义静态方法和类方法。

装饰器的应用场景:

  • 日志记录: 装饰器可用于记录函数的调用信息、参数和返回值。
  • 性能分析: 可以使用装饰器来测量函数的执行时间。
  • 权限控制: 装饰器可用于限制对某些函数的访问权限。
  • 缓存: 装饰器可用于实现函数结果的缓存,以提高性能。

基本语法

Python 装饰允许在不修改原有函数代码的基础上,动态地增加或修改函数的功能,装饰器本质上是一个接收函数作为输入并返回一个新的包装过后的函数的对象。

def decorator_function(original_function):
    def wrapper(*args, **kwargs):
        # 这里是在调用原始函数前添加的新功能
        before_call_code()
        
        result = original_function(*args, **kwargs)
        
        # 这里是在调用原始函数后添加的新功能
        after_call_code()
        
        return result
    return wrapper

# 使用装饰器
@decorator_function
def target_function(arg1, arg2):
    pass  # 原始函数的实现

**解析:**decorator 是一个装饰器函数,它接受一个函数 func 作为参数,并返回一个内部函数 wrapper,在 wrapper 函数内部,你可以执行一些额外的操作,然后调用原始函数 func,并返回其结果。

  • decorator_function 是装饰器,它接收一个函数 original_function 作为参数。
  • wrapper 是内部函数,它是实际会被调用的新函数,它包裹了原始函数的调用,并在其前后增加了额外的行为。
  • 当我们使用 @decorator_function 前缀在 target_function 定义前,Python会自动将 target_function 作为参数传递给 decorator_function,然后将返回的 wrapper 函数替换掉原来的 target_function
def decorator_function(original_function):
    def wrapper(*args, **kwargs):
        # 这里是在调用原始函数前添加的新功能
        print("运行函数前")

        result = original_function(*args, **kwargs)

        # 这里是在调用原始函数后添加的新功能
        print("运行函数后")

        return result

    return wrapper


# 使用装饰器
@decorator_function
def target_function():
    print("运行函数")


target_function()    

使用装饰器

装饰器通过 @ 符号应用在函数定义之前,例如:

@time_logger
def target_function():
    pass

等同于:

def target_function():
    pass
target_function = time_logger(target_function)

这会将 target_function 函数传递给 decorator 装饰器,并将返回的函数重新赋值给 target_function。从而,每次调用 target_function 时,实际上是调用了经过装饰器处理后的函数。

通过装饰器,开发者可以在保持代码整洁的同时,灵活且高效地扩展程序的功能。

带参数的装饰器

装饰器函数也可以接受参数,例如:

def repeat(n):
    def decorator(func):
        def wrapper(*args, **kwargs):
            for _ in range(n):
                result = func(*args, **kwargs)
            return result
        return wrapper
    return decorator

@repeat(3)
def greet(name):
    print(f"Hello, {name}!")

greet("Alice")

以上代码中 repeat 函数是一个带参数的装饰器,它接受一个整数参数 n,然后返回一个装饰器函数。该装饰器函数内部定义了 wrapper 函数,在调用原始函数之前重复执行 n 次。因此,greet 函数在被 @repeat(3) 装饰后,会打印三次问候语。

类装饰器

除了函数装饰器,Python 还支持类装饰器。类装饰器是包含 call 方法的类,它接受一个函数作为参数,并返回一个新的函数。

class DecoratorClass:
    def __init__(self, func):
        self.func = func
    
    def __call__(self, *args, **kwargs):
        # 在调用原始函数之前/之后执行的代码
        result = self.func(*args, **kwargs)
        # 在调用原始函数之后执行的代码
        return result

@DecoratorClass
def my_function():
    pass

数据结构

栈(列表)

  • 压入(Push): 将一个元素添加到栈的顶端。
  • 弹出(Pop): 移除并返回栈顶元素。
  • 查看栈顶元素(Peek/Top): 返回栈顶元素而不移除它。
  • 检查是否为空(IsEmpty): 检查栈是否为空。
  • 获取栈的大小(Size): 获取栈中元素的数量。

自己实现:

class Stack:
    def __init__(self):
        self.stack = []

    def push(self, item):
        self.stack.append(item)

    def pop(self):
        if not self.is_empty():
            return self.stack.pop()
        else:
            raise IndexError("pop from empty stack")

    def peek(self):
        if not self.is_empty():
            return self.stack[-1]
        else:
            raise IndexError("peek from empty stack")

    def is_empty(self):
        return len(self.stack) == 0

    def size(self):
        return len(self.stack)

# 使用示例
stack = Stack()
stack.push(1)
stack.push(2)
stack.push(3)

print("栈顶元素:", stack.peek())  # 输出: 栈顶元素: 3
print("栈大小:", stack.size())    # 输出: 栈大小: 3

print("弹出元素:", stack.pop())  # 输出: 弹出元素: 3
print("栈是否为空:", stack.is_empty())  # 输出: 栈是否为空: False
print("栈大小:", stack.size())    # 输出: 栈大小: 2

队列

队列是一种先进先出(FIFO, First-In-First-Out)的数据结构,意味着最早添加的元素最先被移除。

使用列表时,如果频繁地在列表的开头插入或删除元素,性能会受到影响,因为这些操作的时间复杂度是 O(n)。为了解决这个问题,Python 提供了 collections.deque,它是双端队列,可以在两端高效地添加和删除元素。

使用 collections.deque 实现队列

collections.deque 是 Python 标准库的一部分,非常适合用于实现队列。

from collections import deque

# 创建一个空队列
queue = deque()

# 向队尾添加元素
queue.append('a')
queue.append('b')
queue.append('c')

print("队列状态:", queue)  # 输出: 队列状态: deque(['a', 'b', 'c'])

# 从队首移除元素
first_element = queue.popleft()
print("移除的元素:", first_element)  # 输出: 移除的元素: a
print("队列状态:", queue)            # 输出: 队列状态: deque(['b', 'c'])

# 查看队首元素(不移除)
front_element = queue[0]
print("队首元素:", front_element)    # 输出: 队首元素: b

# 检查队列是否为空
is_empty = len(queue) == 0
print("队列是否为空:", is_empty)     # 输出: 队列是否为空: False

# 获取队列大小
size = len(queue)
print("队列大小:", size)            # 输出: 队列大小: 2

使用列表实现队列

1. 创建队列
queue = []
2. 向队尾添加元素
使用 append() 方法将元素添加到队尾:
queue.append('a')
queue.append('b')
queue.append('c')
print("队列状态:", queue)  # 输出: 队列状态: ['a', 'b', 'c']
3. 从队首移除元素
使用 pop(0) 方法从队首移除元素:
first_element = queue.pop(0)
print("移除的元素:", first_element)  # 输出: 移除的元素: a
print("队列状态:", queue)            # 输出: 队列状态: ['b', 'c']
4. 查看队首元素(不移除)
直接访问列表的第一个元素:
front_element = queue[0]
print("队首元素:", front_element)    # 输出: 队首元素: b
5. 检查队列是否为空
检查列表是否为空:
is_empty = len(queue) == 0
print("队列是否为空:", is_empty)     # 输出: 队列是否为空: False
6. 获取队列大小
使用 len() 函数获取队列的大小:
size = len(queue)
print("队列大小:", size)            # 输出: 队列大小: 2

案例

class Queue:
    def __init__(self):
        self.queue = []

    def enqueue(self, item):
        self.queue.append(item)

    def dequeue(self):
        if not self.is_empty():
            return self.queue.pop(0)
        else:
            raise IndexError("dequeue from empty queue")

    def peek(self):
        if not self.is_empty():
            return self.queue[0]
        else:
            raise IndexError("peek from empty queue")

    def is_empty(self):
        return len(self.queue) == 0

    def size(self):
        return len(self.queue)

# 使用示例
queue = Queue()
queue.enqueue('a')
queue.enqueue('b')
queue.enqueue('c')

print("队首元素:", queue.peek())    # 输出: 队首元素: a
print("队列大小:", queue.size())    # 输出: 队列大小: 3

print("移除的元素:", queue.dequeue())  # 输出: 移除的元素: a
print("队列是否为空:", queue.is_empty())  # 输出: 队列是否为空: False
print("队列大小:", queue.size())    # 输出: 队列大小: 2

文件输入/输出

open

open() 将会返回一个 file 对象,基本语法格式如下:

open(filename, mode)
  • filename:包含了你要访问的文件名称的字符串值。
  • mode:决定了打开文件的模式:只读,写入,追加等。所有可取值见如下的完全列表。这个参数是非强制的,默认文件访问模式为只读(r)。

完整的语法格式为:

open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
  • file: 必需,文件路径(相对或者绝对路径)。
  • mode: 可选,文件打开模式
  • buffering: 设置缓冲
  • encoding: 一般使用utf8
  • errors: 报错级别
  • newline: 区分换行符
  • closefd: 传入的file参数类型
  • opener: 设置自定义开启器,开启器的返回值必须是一个打开的文件描述符。

不同模式打开文件的完全列表:

模式 描述
r 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。
rb 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。
r+ 打开一个文件用于读写。文件指针将会放在文件的开头。
rb+ 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。
w 打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
wb 以二进制格式打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
w+ 打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
wb+ 以二进制格式打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
a 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
ab 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
a+ 打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。
ab+ 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。

下图很好的总结了这几种模式:

模式 r r+ w w+ a a+
+ + + +
+ + + + +
创建 + + + +
覆盖 + +
指针在开始 + + + +
指针在结尾 + +

file对象

序号 方法及描述
1 file.close()关闭文件。关闭后文件不能再进行读写操作。
2 file.flush()刷新文件内部缓冲,直接把内部缓冲区的数据立刻写入文件, 而不是被动的等待输出缓冲区写入。
3 file.fileno()返回一个整型的文件描述符(file descriptor FD 整型), 可以用在如os模块的read方法等一些底层操作上。
4 file.isatty()如果文件连接到一个终端设备返回 True,否则返回 False。
5 file.next()**Python 3 中的 File 对象不支持 next() 方法。**返回文件下一行。
6 [file.read(size])从文件读取指定的字节数,如果未给定或为负则读取所有。
7 [file.readline(size])读取整行,包括 "\n" 字符。
8 [file.readlines(sizeint])读取所有行并返回列表,若给定sizeint>0,返回总和大约为sizeint字节的行, 实际读取值可能比 sizeint 较大, 因为需要填充缓冲区。
9 [file.seek(offset, whence])移动文件读取指针到指定位置
10 file.tell()返回文件当前位置。
11 [file.truncate(size])从文件的首行首字符开始截断,截断文件为 size 个字符,无 size 表示从当前位置截断;截断之后后面的所有字符被删除,其中 windows 系统下的换行代表2个字符大小。
12 file.write(str)将字符串写入文件,返回的是写入的字符长度。
13 file.writelines(sequence)向文件写入一个序列字符串列表,如果需要换行则要自己加入每行的换行符。11111111111111111111

读文件

f.read()

为了读取一个文件的内容,调用 f.read(size), 这将读取一定数目的数据, 然后作为字符串或字节对象返回。

size 是一个可选的数字类型的参数。 当 size 被忽略了或者为负, 那么该文件的所有内容都将被读取并且返回。

f=open("./file/test.txt","r")
str=f.read()
print(str)
f.close()

f.readline()

f.readline() 会从文件中读取单独的一行。换行符为 '\n'。f.readline() 如果返回一个空字符串, 说明已经已经读取到最后一行。

# 打开一个文件
f = open("/tmp/foo.txt", "r")

str = f.readline()

print(str)
#输出:['hello,\n', 'my friend.\n', 'I\n', 'love\n', 'you']

# 关闭打开的文件
f.close()

f.readlines()

f.readlines() 将返回该文件中包含的所有行。

如果设置可选参数 sizehint, 则读取指定长度的字节, 并且将这些字节按行分割。

# 打开一个文件
f = open("./file/test.txt", "r")

str = f.readlines()
print(str)

# 关闭打开的文件
f.close()
# 打开一个文件
f = open("./file/test.txt", "r")

for line in f:
    print(line, end='')

# 关闭打开的文件
f.close()

结果:
hello,
my friend.
I
love
you

写文件

f.write()

f.write(string) 将 string 写入到文件中, 然后返回写入的字符数。

# 打开一个文件
f = open("./file/test.txt", "w")

value = ('www.runoob.com', 14)
s = str(value)
f.write(s)

# 关闭打开的文件
f.close()

#文件内容:('www.runoob.com', 14)

f.tell()

f.tell() 用于返回文件当前的读/写位置(即文件指针的位置)。文件指针表示从文件开头开始的字节数偏移量。f.tell() 返回一个整数,表示文件指针的当前位置。

f.seek()

如果要改变文件指针当前的位置, 可以使用 f.seek(offset, from_what) 函数。

f.seek(offset, whence) 用于移动文件指针到指定位置。

offset 表示相对于 whence 参数的偏移量,from_what 的值, 如果是 0 表示开头, 如果是 1 表示当前位置, 2 表示文件的结尾,例如:

  • seek(x,0) : 从起始位置即文件首行首字符开始移动 x 个字符
  • seek(x,1) : 表示从当前位置往后移动x个字符
  • seek(-x,2):表示从文件的结尾往前移动x个字符

f.close()

在文本文件中 (那些打开文件的模式下没有 b 的), 只会相对于文件起始位置进行定位。

当你处理完一个文件后, 调用 f.close() 来关闭文件并释放系统的资源,如果尝试再调用该文件,则会抛出异常。

序列化

python的pickle模块实现了基本的数据序列和反序列化。

通过pickle模块的序列化操作我们能够将程序中运行的对象信息保存到文件中去,永久存储。

通过pickle模块的反序列化操作,我们能够从文件中创建上一次程序保存的对象。

基本接口:

pickle.dump(obj, file, [,protocol])

有了 pickle 这个对象, 就能对 file 以读取的形式打开:

x = pickle.load(file)

**注解:**从 file 中读取一个字符串,并将它重构为原来的python对象。

file: 类文件对象,有read()和readline()接口。

#!/usr/bin/python3
import pprint, pickle


# 使用pickle模块将数据对象保存到文件
data1 = {'a': [1, 2.0, 3, 4+6j],
         'b': ('string', u'Unicode string'),
         'c': None}

selfref_list = [1, 2, 3]
selfref_list.append(selfref_list)

output = open('data.pkl', 'wb')

# Pickle dictionary using protocol 0.
pickle.dump(data1, output)

# Pickle the list using the highest protocol available.
pickle.dump(selfref_list, output, -1)

output.close()




#使用pickle模块从文件中重构python对象
pkl_file = open('data.pkl', 'rb')

data1 = pickle.load(pkl_file)
pprint.pprint(data1)

data2 = pickle.load(pkl_file)
pprint.pprint(data2)

pkl_file.close()

OS 文件/目录方法

os 模块提供了非常丰富的方法用来处理文件和目录。常用的方法如下表所示:

序号 方法及描述
1 os.access(path, mode) 检验权限模式
2 os.chdir(path) 改变当前工作目录
3 os.chflags(path, flags) 设置路径的标记为数字标记。
4 os.chmod(path, mode) 更改权限
5 os.chown(path, uid, gid) 更改文件所有者
6 os.chroot(path) 改变当前进程的根目录
7 os.close(fd) 关闭文件描述符 fd
8 os.closerange(fd_low, fd_high) 关闭所有文件描述符,从 fd_low (包含) 到 fd_high (不包含), 错误会忽略
9 os.dup(fd) 复制文件描述符 fd
10 os.dup2(fd, fd2) 将一个文件描述符 fd 复制到另一个 fd2
11 os.fchdir(fd) 通过文件描述符改变当前工作目录
12 os.fchmod(fd, mode) 改变一个文件的访问权限,该文件由参数fd指定,参数mode是Unix下的文件访问权限。
13 os.fchown(fd, uid, gid) 修改一个文件的所有权,这个函数修改一个文件的用户ID和用户组ID,该文件由文件描述符fd指定。
14 os.fdatasync(fd) 强制将文件写入磁盘,该文件由文件描述符fd指定,但是不强制更新文件的状态信息。
15 [os.fdopen(fd, mode[, bufsize]]) 通过文件描述符 fd 创建一个文件对象,并返回这个文件对象
16 os.fpathconf(fd, name) 返回一个打开的文件的系统配置信息。name为检索的系统配置的值,它也许是一个定义系统值的字符串,这些名字在很多标准中指定(POSIX.1, Unix 95, Unix 98, 和其它)。
17 os.fstat(fd) 返回文件描述符fd的状态,像stat()。
18 os.fstatvfs(fd) 返回包含文件描述符fd的文件的文件系统的信息,Python 3.3 相等于 statvfs()。
19 os.fsync(fd) 强制将文件描述符为fd的文件写入硬盘。
20 os.ftruncate(fd, length) 裁剪文件描述符fd对应的文件, 所以它最大不能超过文件大小。
21 os.getcwd() 返回当前工作目录
22 os.getcwdb() 返回一个当前工作目录的Unicode对象
23 os.isatty(fd) 如果文件描述符fd是打开的,同时与tty(-like)设备相连,则返回true, 否则False。
24 os.lchflags(path, flags) 设置路径的标记为数字标记,类似 chflags(),但是没有软链接
25 os.lchmod(path, mode) 修改连接文件权限
26 os.lchown(path, uid, gid) 更改文件所有者,类似 chown,但是不追踪链接。
27 os.link(src, dst) 创建硬链接,名为参数 dst,指向参数 src
28 os.listdir(path) 返回path指定的文件夹包含的文件或文件夹的名字的列表。
29 os.lseek(fd, pos, how) 设置文件描述符 fd当前位置为pos, how方式修改: SEEK_SET 或者 0 设置从文件开始的计算的pos; SEEK_CUR或者 1 则从当前位置计算; os.SEEK_END或者2则从文件尾部开始. 在unix,Windows中有效
30 os.lstat(path) 像stat(),但是没有软链接
31 os.major(device) 从原始的设备号中提取设备major号码 (使用stat中的st_dev或者st_rdev field)。
32 os.makedev(major, minor) 以major和minor设备号组成一个原始设备号
33 [os.makedirs(path, mode]) 递归文件夹创建函数。像mkdir(), 但创建的所有intermediate-level文件夹需要包含子文件夹。
34 os.minor(device) 从原始的设备号中提取设备minor号码 (使用stat中的st_dev或者st_rdev field )。
35 [os.mkdir(path, mode]) 以数字mode的mode创建一个名为path的文件夹.默认的 mode 是 0777 (八进制)。
36 [os.mkfifo(path, mode]) 创建命名管道,mode 为数字,默认为 0666 (八进制)
37 [os.mknod(filename, mode=0600, device]) 创建一个名为filename文件系统节点(文件,设备特别文件或者命名pipe)。
38 [os.open(file, flags, mode]) 打开一个文件,并且设置需要的打开选项,mode参数是可选的
39 os.openpty() 打开一个新的伪终端对。返回 pty 和 tty的文件描述符。
40 os.pathconf(path, name) 返回相关文件的系统配置信息。
41 os.pipe() 创建一个管道. 返回一对文件描述符(r, w) 分别为读和写
42 [os.popen(command, mode[, bufsize]]) 从一个 command 打开一个管道
43 os.read(fd, n) 从文件描述符 fd 中读取最多 n 个字节,返回包含读取字节的字符串,文件描述符 fd对应文件已达到结尾, 返回一个空字符串。
44 os.readlink(path) 返回软链接所指向的文件
45 os.remove(path) 删除路径为path的文件。如果path 是一个文件夹,将抛出OSError; 查看下面的rmdir()删除一个 directory。
46 os.removedirs(path) 递归删除目录。
47 os.rename(src, dst) 重命名文件或目录,从 src 到 dst
48 os.renames(old, new) 递归地对目录进行更名,也可以对文件进行更名。
49 os.rmdir(path) 删除path指定的空目录,如果目录非空,则抛出一个OSError异常。
50 os.stat(path) 获取path指定的路径的信息,功能等同于C API中的stat()系统调用。
51 [os.stat_float_times(newvalue]) 决定stat_result是否以float对象显示时间戳
52 os.statvfs(path) 获取指定路径的文件系统统计信息
53 os.symlink(src, dst) 创建一个软链接
54 os.tcgetpgrp(fd) 返回与终端fd(一个由os.open()返回的打开的文件描述符)关联的进程组
55 os.tcsetpgrp(fd, pg) 设置与终端fd(一个由os.open()返回的打开的文件描述符)关联的进程组为pg。
56 os.tempnam([dir[, prefix]]) **Python3 中已删除。**返回唯一的路径名用于创建临时文件。
57 os.tmpfile() **Python3 中已删除。**返回一个打开的模式为(w+b)的文件对象 .这文件对象没有文件夹入口,没有文件描述符,将会自动删除。
58 os.tmpnam() **Python3 中已删除。**为创建一个临时文件返回一个唯一的路径
59 os.ttyname(fd) 返回一个字符串,它表示与文件描述符fd 关联的终端设备。如果fd 没有与终端设备关联,则引发一个异常。
60 os.unlink(path) 删除文件路径
61 os.utime(path, times) 返回指定的path文件的访问和修改的时间。
62 [os.walk(top, topdown=True[, onerror=None[, followlinks=False]]]) 输出在文件夹中的文件名通过在树中游走,向上或者向下。
63 os.write(fd, str) 写入字符串到文件描述符 fd中. 返回实际写入的字符串长度
64 os.path 模块 获取文件的属性信息。
65 os.pardir() 获取当前目录的父目录,以字符串形式显示目录名。
66 os.replace() 重命名文件或目录。

数据库操作

https://www.runoob.com/python3/python3-mysql.html

连接数据库

import pymysql

# 连接到MySQL数据库
connection = pymysql.connect(host='localhost',
                             user='root',
                             password='123456',
                             database='hmdp',
                             cursorclass=pymysql.cursors.DictCursor)

使用数据库

try:
    with connection.cursor() as cursor:
        # 执行SQL查询
        sql = "SELECT * FROM tb_blog"
        cursor.execute(sql)

        # 获取所有记录
        results = cursor.fetchall()
        for id in results:
            print(id)

finally:
    # 关闭数据库连接
    connection.close()

sql = "INSERT INTO sites (name, url) VALUES (%s, %s)"
val = ("RUNOOB", "https://www.runoob.com")
mycursor.execute(sql, val)
 
connection.commit()    # 数据表内容有更新,必须使用到该语句
 
print(mycursor.rowcount, "记录插入成功。")