Python学习过程笔记:主模块(main) 异常处理 命令行参数解析 日志记录 socket模块 类的私有方法 字节字符串

1.Python中的主程序

if __name__ == '__main__'

在Python中,if __name__ == '__main__' 是一个常见的代码块。它的作用是判断当前模块是否作为主程序直接运行,还是作为模块被其他程序导入使用。

当一个 Python 脚本被直接执行时,其 __name__ 属性的值会被设置为 '__main__'。而当该脚本被作为模块导入时,__name__ 的值将是模块的名称。

因此,通过使用 if __name__ == '__main__' 条件判断,我们可以将一些代码片段放在这个条件块内,这些代码只有在该脚本作为主程序执行时才会被执行,而在作为模块被导入时不会执行。

这种用法通常用于将某些测试代码或者执行特定任务的代码放在主程序中,而不会在模块导入时自动执行。这样做可以使模块更加灵活和可重用。

2.Python中的异常处理

在 Python 中,try 块用于捕获可能引发异常的代码。其语法结构如下:

try:
    # 可能引发异常的代码
except ExceptionType1:
    # 处理 ExceptionType1 类型的异常
except ExceptionType2:
    # 处理 ExceptionType2 类型的异常
else:
    # 当没有异常发生时执行的代码
finally:
    # 无论是否发生异常都会执行的代码
  • try模块try 块中包含的代码是可能会引发异常的部分。如果在 try 块中的代码引发了异常,Python 将跳过剩余的 try 块代码,并找到与引发的异常类型匹配的 except 块来处理异常。
  • except部分except 块可以有零个或多个,用于处理特定类型的异常。可以指定异常类型,如
    ExceptionType1ExceptionType2 等,也可以使用通用的 Exception 来捕获所有异常。当引发的异常类型与某个 except 块指定的异常类型匹配时,该 except 块中的代码将被执行。
  • else部分else 块是可选的,它包含的代码将在 try 块中的代码没有引发任何异常时执行。通常在 else块中可以放置处理没有异常发生时的逻辑。
  • finally块finally 块也是可选的,它包含的代码无论是否发生异常都会被执行。通常在 finally 块中放置一些清理资源的代码,例如关闭打开的文件或释放其他资源。

注意事项except 块至少需要一个,而 else 块和 finally 块都是可选的。try 块和至少一个 except 块是最基本的语法结构,用于捕获和处理异常。

3.Python中的命令行参数解析

argparse 是 Python 标准库中的一个模块,用于解析命令行参数和生成用户友好的命令行界面。其中,ArgumentParserargparse 模块中的一个重要类。

ArgumentParser 类是用来定义命令行参数的解析规则,它提供了一种简单而灵活的方式来处理命令行参数。通过创建一个 ArgumentParser 对象,你可以定义程序所需的参数,并编写代码来处理这些参数。

下面是 ArgumentParser 类的一些常用方法:

 ArgumentParser(prog=None, description=None, epilog=None)
  • 创建一个 ArgumentParser 对象。prog 参数用于指定程序的名称(默认为 sys.argv[0]),description 参数用于添加程序的描述信息,epilog 参数用于添加程序的结尾信息。一般情况下可以不加参数地进行创建。
.add_argument(name or flags, action, nargs, const, default, type, choices, required, help, metavar)

定义一个命令行参数。这个方法有很多参数,其中一些常用的包括:

  • name or flags:参数的名称或者选项标志。
  • action:参数的动作,默认为存储参数值。一般情况下无需设置这个参数。
  • nargs:参数的个数,可以是固定值或者可变数量。其中nargs='?' 表示参数可以有零个或一个值。
  • const:某些动作(如 store_const)时使用的常量值。
  • default:参数的默认值。
  • type:参数的类型。
  • choices:参数值的限定范围。
  • required:参数是否是必需的。
  • help:参数的帮助信息。
  • metavar:参数在帮助信息中显示的名称。
.parse_args(args=None, namespace=None)

解析命令行参数,并返回一个命名空间对象,其中包含参数的值。args 参数是一个字符串列表,用于指定要解析的命令行参数。如果不提供 args 参数,则默认使用 sys.argv[1:]。namespace 参数用于指定命名空间对象,如果不提供,则会创建一个新的命名空间对象。

4.Python中的日志记录

Python 的 logging 模块是一个用于记录日志的强大工具,它提供了灵活的日志记录功能,可以帮助你在应用程序中捕获、记录和管理各种类型的日志信息。

下面是 logging 模块的一些核心组件和概念:

  • LoggerLoggerlogging 模块最主要的组件之一。它提供了记录日志消息的方法,如 debug()info()warning()error()critical()。你可以创建多个 Logger 实例,用于不同的日志记录需求。
  • HandlerHandler 用于确定日志记录的目的地,例如控制台、文件或网络。logging 模块提供了多种类型的 Handler,如 StreamHandlerFileHandlerRotatingFileHandlerTimedRotatingFileHandler 等。
  • FormatterFormatter 确定日志消息的输出格式。你可以定义自定义的格式,包括日期、时间、日志级别、日志信息等。
  • FilterFilter 用于过滤和选择要记录的日志消息。通过应用过滤器,你可以决定哪些日志消息应该被记录下来,哪些应该被忽略。
  • Logger.setLevel():通过调用 setLevel() 方法,你可以设置日志记录的最低级别。只有达到该级别或更高级别的日志消息才会被记录。
  • Logger.addHandler():使用 addHandler() 方法,你可以将一个或多个处理程序(Handler)添加到日志记录器(Logger)中。这样,日志消息将被传递给这些处理程序进行处理。

使用 logging 模块记录日志的基本步骤如下:

  • 导入 logging 模块。
  • 创建一个 Logger 实例。
  • 创建一个或多个 Handler 实例,并设置它们的级别和格式。
  • Handler 添加到 Logger 中。
  • 使用 Logger 的记录方法记录日志消息。

下面是一个简单的示例,演示了如何使用 logging 模块记录日志:

import logging

# 创建 Logger 实例
logger = logging.getLogger('my_logger')
logger.setLevel(logging.DEBUG)

# 创建文件处理程序
file_handler = logging.FileHandler('app.log')
file_handler.setLevel(logging.INFO)

# 创建控制台处理程序
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.DEBUG)

# 创建 Formatter
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

# 将 Formatter 应用于处理程序
file_handler.setFormatter(formatter)
console_handler.setFormatter(formatter)

# 将处理程序添加到 Logger
logger.addHandler(file_handler)
logger.addHandler(console_handler)

# 记录日志消息
logger.debug('Debug message')
logger.info('Info message')
logger.warning('Warning message')
logger.error('Error message')
logger.critical('Critical message')

在上面的示例中,我们创建了一个名为 my_loggerLogger 实例,并设置其级别为 DEBUG。然后,我们创建了一个文件处理程序和一个控制台处理程序,并为它们设置了级别和格式。最后,我们将这两个处理程序添加到 Logger 中,并使用 Logger 的记录方法记录了不同级别的日志消息。

logging 模块中,日志级别是通过整数值来表示的,具有以下预定义的级别(按照从低到高的顺序排列):

  • DEBUG:用于详细的调试信息。
  • INFO:用于提供程序的运行信息。
  • WARNING:用于表示可能的问题,但不会影响程序的正常运行。
  • ERROR:用于表示错误情况,但程序仍能继续运行。
  • CRITICAL:用于表示严重的错误,可能导致程序无法继续运行。

这些级别的整数值分别是 10、20、30、40 和 50。级别值越低,表示的日志级别越低;级别值越高,表示的日志级别越高。

当设置 LoggerHandler 的级别时,只有达到该级别或更高级别的日志消息才会被记录。例如,如果将 Logger 的级别设置为 WARNING,那么 WARNINGERRORCRITICAL 级别的日志消息将被记录,而 DEBUGINFO 级别的日志消息将被忽略。

此外,logging 模块还提供了一个特殊的级别 NOTSET,其整数值为 0。如果将 LoggerHandler 的级别设置为 NOTSET,它将使用其父级别的级别。如果没有父级别,则默认级别为 WARNING

5.网络编程socket模块

当涉及到网络编程时,Python中的socket模块是一个重要的工具。它允许你创建套接字对象来实现网络通信。

以下是对socket模块的简单介绍:

  • 套接字:套接字(Socket)是网络通信的基本组件,用于在不同主机之间传输数据。socket()函数用于创建套接字对象。需要指定地址族(如AF_INET表示IPv4)和套接字类型(如SOCK_STREAM表示TCP套接字)。一旦创建了套接字对象,可以使用bind()方法将套接字绑定到特定的地址和端口上。
  • 侦听:通过使用listen()方法,可以开始侦听传入的连接请求。
  • 接收连接:服务器可以使用accept()方法接受客户端的连接请求,并创建一个新的套接字对象来处理与客户端的通信。一旦建立连接,可以使用套接字对象的send()方法发送数据,使用recv()方法接收数据。

以下是一个简单的示例,展示了如何使用socket模块创建一个简单的TCP服务器:

import socket

# 创建套接字对象
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 绑定地址和端口
server_address = ('localhost', 8888)
server_socket.bind(server_address)

# 监听连接
server_socket.listen(1)
print('服务器正在监听端口 8888...')

# 接受连接并处理请求
while True:
    client_socket, client_address = server_socket.accept()
    print('接受来自', client_address, '的连接')

    # 接收数据
    data = client_socket.recv(1024)
    print('接收到的数据:', data.decode())

    # 发送响应
    response = 'Hello, client!'
    client_socket.send(response.encode())

    # 关闭连接
    client_socket.close()

在上面的示例中,我们创建了一个TCP服务器,绑定到本地主机的端口8888。服务器开始监听连接,并在接受连接后接收客户端发送的数据,并发送响应。

另外,当需要获取当前主机的主机名用于在bind函数中绑定套接字时,可以使用socket.gethostname() 函数。该函数通过查询操作系统来获取主机名。它返回一个字符串,表示当前主机的主机名。

下面将辨析一下socket模块中的send方法和sendall方法:

在Python的socket模块中,send()函数和sendall()函数都用于发送数据到已连接的套接字,但它们在处理数据的方式上有一些区别。

  • send方法send()函数用于发送数据块。它将尽可能多地发送指定的数据,并返回实际发送的字节数。如果send()无法立即发送所有数据(例如,套接字的发送缓冲区已满),它可能只发送部分数据。在这种情况下,你可以再次调用send()来发送剩余的数据。
  • sendall方法sendall()函数也用于发送数据块,但它会尽力发送所有指定的数据。它会持续发送数据,直到所有数据都被发送成功,或者发生错误。如果在发送过程中发生错误,sendall()函数将引发异常。因此,它可以保证在发送所有数据之前不会返回。

选择使用哪个函数取决于需求。如果希望在发送数据时能够了解实际发送的字节数,或者需要手动处理发送剩余的数据,那么可以使用send()函数。如果希望确保所有数据都被完整地发送并且不想手动处理发送错误,那么可以使用sendall()函数。

6.Python中的私有方法

在Python中,没有严格意义上的私有方法。然而,约定上使用双下划线(__)作为方法名的前缀,可以将方法标识为类的内部使用,即表示它们是私有方法。

当方法名以双下划线开头时,Python解释器会自动对方法名进行名称修饰(name mangling),将其转换为_ClassName__method的形式。这样做是为了防止在子类中意外地覆盖父类的方法。

7.Python中的字节字符串

在Python中,有两种主要的字符串类型:字符串(str)和字节字符串(bytes)。

  • 字符串:字符串(str)是由Unicode字符组成的序列,用于表示文本数据。字符串在Python中是不可变的,可以使用单引号或双引号括起来,例如 ‘Hello’ 或 “World”。
  • 字节字符串:字节字符串(bytes)是由字节组成的序列,用于表示二进制数据。字节字符串在Python中也是不可变的,以b开头,可以使用单引号或双引号括起来,例如 b'\x48\x65\x6c\x6c\x6f'

在处理文本数据时,通常使用字符串(str)类型。而在处理二进制数据(例如文件读写、网络传输等)时,使用字节字符串(bytes)类型更为常见。

在进行网络传输时,往往使用字节字符串而不是字符串的原因有几个:

  • 网络传输的基本单位是字节:计算机网络是以字节为单位进行数据传输的。无论是在互联网上还是在本地网络中,数据都是以二进制形式通过网络传输的。因此,将数据编码为字节字符串可以更直接地映射到网络传输的实际数据。
  • 二进制数据的表达和传输效率更高:在网络传输中,往往需要处理各种类型的数据,包括文本、图像、音频、视频等。这些数据通常以二进制形式表示,并且使用特定的编码方案进行传输。使用字节字符串可以更有效地表示和处理这些二进制数据,而不会引入额外的转换和处理开销。
  • 字符编码和字符集的一致性问题:在跨越不同计算机系统、操作系统和国家地区的网络传输中,字符编码和字符集的一致性问题是一个重要考虑因素。字符串在不同的编码方案下可能会有不同的表示形式,而字节字符串则是直接的二进制数据表示形式。通过使用字节字符串,可以避免字符编码和字符集之间的不一致性问题,从而减少数据传输中的潜在错误和混淆。
  • 兼容性和互操作性:字节字符串是一种通用的数据表示形式,几乎可以在任何编程语言和平台上使用。它们具有更广泛的兼容性和互操作性,能够无缝地与各种网络协议和数据传输库进行集成。

在Python中,encode() 是字符串对象的方法,用于将字符串编码为字节字符串。它接受一个参数,即指定要使用的字符编码方案。

下面是 encode() 方法的基本语法:

encoded_bytes = string.encode(encoding)

其中:

  • string 是要编码的字符串。
  • encoding 是一个字符串,指定要使用的字符编码方案。常见的字符编码方案包括 UTF-8、ASCII、Latin-1 等。

Guess you like

Origin blog.csdn.net/hanmo22357/article/details/132271070