Python从入门到入土-基本技能

2022-11-28 15:50:02 浏览数 (1)

CSDN话题挑战赛第2期 参赛话题:学习笔记

命令行解析

手工编写 Python 命令行解析,支持 ‘-x’ 或者 ‘–x’ 类型选项处理,如果没有指定值则设置为True。

代码语言:javascript复制
import sys


def error(info):
    print(info)
    sys.exit(0)


def parse_option(token):
    if len(token) == 0 or len(token) == 1 or token[0] != '-':
        error("格式错误,选项长度至少大于2并且第一个字符必须是 '-'")

    if token[1] != '-':
        return token[1:]

    if len(token) == 2 or token[2] == '-':
        error("格式错误,不支持空选项 '--' 或则三横杆选项 '---x' ")

    return token[2:]


def parse_value(token):
    if token is None:
        return True

    if len(token) == 0:
        return True

    if token[0] == '-':
        error('格式错误')
    else:
        return token


if __name__ == '__main__':
    count = len(sys.argv)
    options = {}

    # 在此使用 parse_option 和 parse_value 解析命令行
    i = 1
    while i < count:
        token = sys.argv[i]
        next_token = None
        if i   1 < count:
            next_token = sys.argv[i   1]
            i = i   1

        option = parse_option(token)
        value = parse_value(next_token)

        options[option] = value
        i  = 1

    for option in options:
        value = options[option]
        print("{}={}".format(option, value))

使用 optparse 库配置指定命令行选项,并解析命令行

  1. 选项 ‘-s’ 和选项 ‘–server’ 等价
  2. 选项 ‘–host’ 设置默认为 0.0.0.0
  3. 选项 ‘–port’ 设置默认为 80
  4. 选项 ‘–ssl’ 如果指定,则 option.ssl=True。
代码语言:javascript复制
# 使用 optparse 库配置指定命令行选项,并解析命令行
# 1. 选项 '-s' 和选项 '--server' 等价
# 2. 选项 '--host' 设置默认为 0.0.0.0
# 3. 选项 '--port' 设置默认为 80
# 4. 选项 '--ssl' 如果指定,则 option.ssl=True。
from ast import parse
from optparse import OptionParser

if __name__ == "__main__":
    parser = OptionParser()

    # 在此添加上述要求的4个命令行参数选项配置
    parser.add_option(
        "-s", "--server",
        dest="server",
        help="server",
        metavar="SERVER"
    )

    parser.add_option(
        "-h", "--host",
        dest="host",
        help="host",
        default='0.0.0.0',
        metavar="HOST"
    )

    parser.add_option(
        '-p', "--port",
        dest="port",
        help="port",
        default='80',
        metavar="PORT"
    )

    parser.add_option(
        "--ssl",
        dest="ssl",
        help="ssl",
        action="store_true",
        metavar="SSL"
    )

    (options, args) = parser.parse_args()
    print(f"server={options.server}")
    print(f"host={options.host}")
    print(f"port={options.port}")
    print(f"ssl={options.ssl}")

时间日期

计算昨天和明天的日期:

代码语言:javascript复制
from datetime import datetime, timedelta

if __name__ == '__main__':
    today = datetime.now()
    print(today)
    print(today.strftime("%d/%m/%y"))
    print(today.strftime("%A %d %B %Y"))

    # 在此计算昨天和明天日期
    # yesterday = today   timedelta(weeks=0, days=-1)
    # nextday = today   timedelta(weeks=0, days=1)

    yesterday = today - timedelta(days=1)
    nextday = today - timedelta(days=-1)

    # yesterday = today   timedelta(days=-1)
    # nextday = today   timedelta(days=1)
    print(yesterday)
    print(nextday)

便利的 Python 计时器,统计从 0 遍历到 100000 消耗的时间,精确到毫秒。

代码语言:javascript复制
# 便利的 Python 计时器,统计从 0 遍历到 100000 消耗的时间,精确到毫秒

from datetime import datetime
from time import time, mktime

class TimeSpan:
    def __init__(self) -> None:
        self.start = round(time() * 1000)

    # 在此计算从开始到现在的耗时,精确到毫秒
    def elapse_mill_secs(self):
        end = round(datetime.now().timestamp() * 1000)
        return end - self.start

    # def elapse_mill_secs(self):
    #     end = round(time() * 1000)
    #     return end - self.start

    # def elapse_mill_secs(self):
    #     end = round(mktime(datetime.now().timetuple()) * 1000)
    #     return end - self.start


    def elapse_secs(self):
        return (self.elapse_mill_secs())/1000

if __name__ == '__main__':
    s = TimeSpan()

    for i in range(0, 100000):
        pass
    print('耗时: {} 毫秒'.format(s.elapse_mill_secs()))
    print('耗时: {} 秒'.format(s.elapse_secs()))

从2008年1月开始到本月,遍历每一个月份的1号,并打印信息。

代码语言:javascript复制
from datetime import date, timedelta
from calendar import monthrange

def next_month(d):
    # 在此实现计算下一个月的代码
    # 方式一
    # offset = monthrange(d.year, d.month)
    # first_weeky_day, days_in_month = offset
    # value = d   timedelta(days_in_month)
    # 方式二
    # days_in_month = monthrange(d.year, d.month)[1]
    # value = d   timedelta(days_in_month)
    # 方式三
    offset = monthrange(d.year, d.month)
    days_in_month = offset[1]
    value = d   timedelta(days_in_month)
    return value

def for_each_month(start, finish, action):
    while start < finish:
        action(start)
        start = next_month(start)

if __name__ == '__main__':
    for_each_month(
        date(2008, 1, 1),
        date.today(),
        lambda d: print(d)
    )

数据文件读写

Python 创建文件夹

使用 os 递归创建文件夹,已存在就覆盖

代码语言:javascript复制
import os
if __name__ == '__main__':
    os.makedirs(
        "/tmp/test/test/test/",
        exist_ok=True
    )

Python 文件夹拷贝

实现文件夹拷贝,要求如下:

  1. 使用 shutil 拷贝 “copy.py” 文件到 “/tmp/copy.py”
  2. 拷贝 “copy.py” 文件到 “/tmp/copy2.py”, 保留元数据
  3. 递归拷贝目录 “./” 到 “/tmp/file_test/”,如果已存在就覆盖
代码语言:javascript复制
# 实现文件夹拷贝,要求如下:
#
# 使用 shutil 拷贝 "copy.py" 文件到 "/tmp/copy.py"
# 拷贝 "copy.py" 文件到 "/tmp/copy2.py", 保留元数据
# 递归拷贝目录 "./" 到 "/tmp/file_test/",如果已存在就覆盖

import shutil

def test():
    # 拷贝文件
    shutil.copy(
        "copy.py",
        "/tmp/copy.py"
    )

    # 拷贝文件,保持元数据
    shutil.copy2(
        "copy.py",
        "/tmp/copy2.py"
    )

    # 递归拷贝目录
    shutil.copytree(
        "./",
        "/tmp/file_test/",
        dirs_exist_ok=True
    )

if __name__ == '__main__':
    test()

文件遍历

稳定排序地遍历一个文件下的文件

代码语言:javascript复制
# 稳定排序地遍历一个文件下的文件

import os

def ordered_list_dir(dir):
    entries = os.listdir(dir)
    entries.sort()
    return entries

if __name__ == '__main__':
    entries = ordered_list_dir('./')
    for entry in entries:
        print(entry)
代码语言:javascript复制
# 遍历一个文件夹下的所有子文件夹,并返回所有'config.json'文件的绝对路径列表

import os

def retrieve_file_paths(dir_name):
    file_paths = []
    abs_dir_name = os.path.abspath(dir_name)

    # 在此实现遍历代码
    for base, dirs, files in os.walk(abs_dir_name):
        for dir in dirs:
            cfg_file = os.path.join(base, dir, 'config.json')
            if os.path.exists(cfg_file):
                file_paths.append(cfg_file)

    return file_paths

if __name__ == '__main__':
    file_paths = retrieve_file_paths('./')
    print(file_paths)

文件统计

统计文件中行数,非空行数,以及空格间隔的token数

代码语言:javascript复制
# 统计文件中行数,非空行数,以及空格间隔的token数

# -*- coding: UTF-8 -*-
import json

def count_file(file):
    line_count = 0
    non_empty_line_count = 0
    token_count = 0

    with open(file, 'r') as f:
        while True:
            # 读取每行
            line = f.readline()
            if not line:
                break

            line_count  = 1
            line_len = len(line)
            line_token_count = 0

            # 实现统计单行token数
            blank = False
            for char in line:
                if char in [' ', 't', 'b']:
                    blank = True
                else:
                    if blank:
                        line_token_count  = 1
                    blank = False

            token_count  = line_token_count
            if line_token_count > 0:
                non_empty_line_count  = 1

    return {
        'file': file,
        'line_count': line_count,
        'line_token_count': token_count,
        'non_empty_line_count': non_empty_line_count
    }

if __name__ == '__main__':
    ret = count_file('count_file.py')
    print('行数:', ret['line_count'])
    print('非空行:', ret['non_empty_line_count'])
    print('非空词数:', ret['line_token_count'])
    with open('/tmp/count.json', 'w') as f:
        f.write(json.dumps(ret, indent=2, ensure_ascii=False))

文件夹压缩

使用shutil对文件夹进行zip压缩,压缩过程显示进度条

代码语言:javascript复制
# 使用shutil对文件夹进行zip压缩,压缩过程显示进度条

import os
import shutil
import logging
from progress.bar import IncrementalBar

logger = logging.getLogger(__name__)


def count_files_in_dir(dir):
    totalFiles = 0
    for base, dirs, files in os.walk(dir):
        totalFiles  = len(files)
    return totalFiles


def zip_with_progress(dir_path, zip_file):
    bar = None
    total_files = count_files_in_dir(dir_path)

    # 进度条显示
    def progress(*args, **kwargs):
        if not args[0].startswith('adding'):
            return

        nonlocal bar, total_files
        if bar is None:
            print('@开始压缩:{}'.format(zip_file))
            bar = IncrementalBar('正在压缩:', max=total_files)
        bar.next(1)

    # 调用shutil.make_archive时,临时替换其 logger 参数,用来显示进度条
    old_info = logger.info
    logger.info = lambda *args, **kwargs: progress(*args, **kwargs)
    shutil.make_archive(dir_path, 'zip', dir_path, logger=logger)
    logger.info = old_info

    if bar is not None:
        bar.finish()


if __name__ == '__main__':
    zip_with_progress('./', '/tmp/test_file_zip.zip')
    print()

0 人点赞