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


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

    命令行解析

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

    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))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

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

    1. 选项 ‘-s’ 和选项 ‘–server’ 等价
    2. 选项 ‘–host’ 设置默认为 0.0.0.0
    3. 选项 ‘–port’ 设置默认为 80
    4. 选项 ‘–ssl’ 如果指定,则 option.ssl=True。
    # 使用 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}")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    时间日期

    计算昨天和明天的日期:

    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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

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

    # 便利的 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()))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

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

    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)
        )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    数据文件读写

    Python 创建文件夹

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

    import os
    if __name__ == '__main__':
        os.makedirs(
            "/tmp/test/test/test/",
            exist_ok=True
        )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    Python 文件夹拷贝

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

    1. 使用 shutil 拷贝 “copy.py” 文件到 “/tmp/copy.py”
    2. 拷贝 “copy.py” 文件到 “/tmp/copy2.py”, 保留元数据
    3. 递归拷贝目录 “./” 到 “/tmp/file_test/”,如果已存在就覆盖
    # 实现文件夹拷贝,要求如下:
    #
    # 使用 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()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    文件遍历

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

    # 稳定排序地遍历一个文件下的文件
    
    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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    # 遍历一个文件夹下的所有子文件夹,并返回所有'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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    文件统计

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

    # 统计文件中行数,非空行数,以及空格间隔的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))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    文件夹压缩

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

    # 使用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()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
  • 相关阅读:
    Redis在中国火爆,为何MongoDB更受欢迎国外?
    代理模型学习记录
    C++--多态
    Swing
    手把手教你Magisk安装
    SQL注入漏洞(原理篇)
    Apache shiro RegExPatternMatcher 权限绕过漏洞 (CVE-2022-32532)
    优秀程序员是怎么思考的?
    Python tkinter实现复刻Windows记事本UI和菜单的文本编辑器(一)
    腾讯二面 高级Java开发工程师
  • 原文地址:https://blog.csdn.net/qq_35427589/article/details/126947219