Python Notes (1) - Syntax and Strings

转载请注明出处: http://blog.youkuaiyun.com/cxsydjn/article/details/71302732

The note introduces basic Python syntax and strings.

Python notes of open courses @Codecademy.

Brief Introduction

Python is a high level scripting language with object oriented features.

Python programs can be written using any text editor and should have the extension .py.

You may click to Python Basics for more details.

Python Syntax

  • Variables and Data Types
    • Var_name = X. X could be int 5 / float 1.23 / boolean True (or False)
  • Whitespace
    • Important. Have to be careful with how to use it.
    • Should indent your code with correct (usually four) spaces.
  • Comments
    • Single Line: #
    • Multi-Line: """ bla…bla… """
  • Operators and Maths

    • Add, subtract, multiply, divide numbers like +, -, *, /
    • Exponentiation: **
    • Modulo (which returns the remainder from a division): %

      
      # Examples for `/`
      
      5 / 2
      
      # 2
      
      
      5.0 / 2
      
      # 2.5
      
      
      float(5) / 2
      
      # 2.5
      
    • When you divide an integer by another integer, the result is always an integer (rounded down, if needed).

    • When you divide a float by an integer, the result is always a float.
    • To divide two integers and end up with a float, you must first use float() to convert one of the integers to a float.
  • External Resources

Strings

  • Strings
    • String: can contain letters, numbers, and symbols. A string could created by 'String', "String", or str(3.14).
    • Escaping Characters: 'There's' should be written as 'There\'s'
    • Access by Index: In Python, we start counting the index from zero instead of one. E.g., c = "cats"[0].
  • String Methods
    • len(): gets the length (the number of characters) of a string. E.g., len(str_name) or len("String")
    • lower(): gets rid of all the capitalization in strings. E.g., str_name.lower()
    • upper(): makes a string completely upper case. E.g., str_name.upper()
    • str(): turns non-strings into strings. E.g., str(str_name)
    • Dot Notation: Methods that use dot notation only work with strings. Additionally, len() and str() can work on other data types.
  • Print

    • print: simply displays your code in the console.
    • String Concatenation: The + operator between strings will ‘add’ them together, one after the other. E.g., print "I " + "love " + "python", you might get I love python
    • Explicit String Conversion: combines a string with something that isn’t a string using str(). E.g., print "I love python " + str(3.0), you might got I love python 3.0
    • String Formatting with %: The % operator after a string is used to combine a string with variables. The % operator will replace a %s in the string with the string variable that comes after it. E.g.,

      
      # Example 1
      
      string_1 = "you"
      string_2 = "me"
      
      print "I love %s! Do you love %s?" % (string_1, string_2)
      
      
      # Example 2  
      
      name = raw_input("Question1")
      quest = raw_input("Question2")
      color = raw_input("Question3")
      
      print "Answer to Q1 is %s, answer to Q2 is %s, " \
      "and answer to Q3 is %s." % (A1, A2, A3)
  • Date and Time

    • datetime: keeps track of time when something happened.
    • datetime.now(): to retrieve the current date and time.
    • Extracting Information: year, month, day, hour, minute, and second from datetime.now().
    • Print as yyyy-mm-dd, mm/dd/yyyy and hh:mm:ss: see examples below

      
      # Using the first row to import the **datetime library**.
      
      from datetime import datetime
      
      now = datetime.now()
      
      
      # Extracting Information
      
      current_year = now.year
      current_month = now.month
      current_day = now.day
      
      
      # print date as `yyyy-mm-dd` and `mm/dd/yyyy`
      
      print '%s-%s-%s' % (now.year, now.month, now.day)
      print '%s/%s/%s' % ( now.month, now.day, now.year)
      
      
      # print time as `hh:mm:ss`
      
      print '%s:%s:%s' % ( now.hour, now.minute, now.second)

External Resources

<think>我们注意到错误信息提示语法错误,指向一个f-string。在Python 3.6之前,f-string是不可用的。因此,我们需要检查用户使用的Python版本。如果用户使用的是Python 3.5或更早版本,则不能使用f-string。 但是,在脚本的开头我们指定了`#!/usr/bin/env python`,这可能会使用Python 2。为了避免这个问题,我们可以将shebang改为`#!/usr/bin/env python3`,或者将f-string替换为旧式的字符串格式化方法。 考虑到兼容性,我们可以将所有的f-string替换为`.format()`方法。此外,错误发生在第58行,也就是在`parse_du_file`函数中的打印语句。 修改方案: 将 `print(f"解析DU文件错误: {str(e)}")` 改为 `print("解析DU文件错误: {}".format(str(e)))` 同时,我们需要检查整个脚本,将所有f-string替换掉。 由于用户要求输出修改后的完整脚本,我们需要替换所有f-string。 但是,我们观察到错误发生在第一个f-string的位置(第58行),因此我们至少需要修改此处。为了确保兼容性,最好全部替换。 另外,注意在`parse_lpdump_file`函数中也有f-string,同样需要修改。 修改步骤: 1. 将所有的f"..." 改为 "..." .format(...) 的形式。 我们来看几个例子: 原代码:`print(f"处理目录: {folder_path}")` 改为:`print("处理目录: {}".format(folder_path))` 原代码:`print(f"解析LPdump文件: {lpdump_file}")` 改为:`print("解析LPdump文件: {}".format(lpdump_file))` 原代码:`return f"错误: 目录不存在 - {folder}"` 改为:`return "错误: 目录不存在 - {}".format(folder)` 注意:有些f-string中包含了多个变量,需要按顺序放入format的参数中。 另外,在字符串格式化时,注意转义大括号。 由于脚本较长,我们只修改出现f-string的地方。根据之前的脚本,我们找出所有f-string并修改。 根据提供的脚本,f-string出现在以下位置(行号可能变化,我们根据上下文修改): - 在parse_du_file函数中:有一处 - 在parse_lpdump_file函数中:有一处 - 在generate_dual_report函数中:多处(包括print和return语句) 我们重新输出修改后的完整脚本,将所有的f-string替换为.format()方式。 同时,为了避免使用Python2执行,我们可以将shebang改为`#!/usr/bin/env python3`。 但是,用户可能没有安装python3,所以我们也可以选择保留为python,但要求用户使用Python3。在代码中添加版本检查是一个好习惯,但为了简化,我们只修改字符串格式。 此外,我们注意到在解析LPdump文件的正则表达式中,有一处使用了原始字符串,这个不需要修改。 下面我们输出修改后的完整脚本。 </think>根据错误信息,您遇到了Python语法错误,是由于使用了f-strings格式化字符串(Python 3.6+特性)但在旧版Python环境中运行所致。以下是完全兼容Python 3.5及以下版本的修正脚本: ```python #!/usr/bin/env python # -*- coding: utf-8 -*- import os import re import sys import argparse import xlwt from collections import defaultdict # 分区名称映射表(前缀 → 友好名称) PARTITION_NAME_MAP = { '02_': 'system', '03_': 'vendor', '04_': 'product', '05_': 'odm', '06_': 'my_product', '07_': 'my_engineering', '08_': 'my_stock', '09_': 'my_heytap', '10_': 'my_company', '11_': 'my_carrier', '12_': 'my_region', '13_': 'my_preload', '14_': 'data', '15_': 'my_bigball', '16_': 'my_manifest', '17_system_dlkm': 'system_dlkm', '17_vendor_dlkm': 'vendor_dlkm', '17_cache': 'cache', '18_': 'super_partition' # LPdump分区映射 } SECTOR_SIZE = 512 # 默认扇区大小(字节) def parse_du_file(file_path): """解析du命令输出文件并转换为MB""" data = {} try: with open(file_path, 'r', encoding='utf-8', errors='ignore') as f: for line in f: if 'Permission denied' in line or 'No such file' in line or not line.strip(): continue # 匹配格式: 大小 单位 路径 match = re.match(r'(\d+\.?\d*)\s*([KMG]?)[Bb]?\s+(.*)', line.strip()) if match: size, unit, path = match.groups() size = float(size) # 单位转换到MB if unit == 'K': size = size / 1024.0 elif unit == '': size = size / (1024*1024.0) # 字节 elif unit == 'M': pass # 已经是MB elif unit == 'G': size = size * 1024.0 data[path] = round(size, 4) except Exception as e: print("解析DU文件错误: {}".format(str(e))) return data def parse_lpdump_file(file_path): """解析lpdump文件,提取分区大小(MB)""" partition_sizes = {} try: with open(file_path, 'r', encoding='utf-8', errors='ignore') as f: capturing = False for line in f: if "Super partition layout:" in line: capturing = True continue if capturing and "-------" in line: continue if capturing: if not line.strip(): break # 遇到空行停止捕获 # 解析格式: super: 2048 .. 1904992: system_a (1902944 sectors) match = re.match( r'super:\s+\d+\s+\.\.\s+\d+:\s+([\w_]+)\s+\((\d+)\s+sectors?\)', line.strip() ) if match: part_name, sectors = match.groups() # 提取基础分区名 (去除_a/_b后缀) base_name = re.sub(r'_[ab]$', '', part_name) # 计算MB: sectors * SECTOR_SIZE / (1024*1024) size_mb = int(sectors) * SECTOR_SIZE / (1024 ** 2) partition_sizes[base_name] = round(size_mb, 4) except Exception as e: print("解析LPdump文件错误: {}".format(str(e))) return partition_sizes def extract_file_prefix(filename): """提取文件前缀""" if filename.startswith('17_'): return filename.replace('.txt', '') match = re.match(r'^(\d+_)', filename) return match.group(1) if match else None def is_main_partition_file(filename, prefix): """检查是否为主分区文件""" if prefix is None: return False if prefix.startswith('17_'): return True expected_name = prefix + PARTITION_NAME_MAP[prefix] + ".txt" return filename == expected_name def generate_dual_report(folder1, folder2, output_xlsx): """生成双机对比报告""" folder1_name = os.path.basename(os.path.normpath(folder1)) folder2_name = os.path.basename(os.path.normpath(folder2)) # 验证目录存在 for folder in [folder1, folder2]: if not os.path.exists(folder): return "错误: 目录不存在 - {}".format(folder) if not os.path.isdir(folder): return "错误: 路径不是目录 - {}".format(folder) # 初始化数据结构 machine1_main_data = defaultdict(dict) machine2_main_data = defaultdict(dict) machine1_all_files = defaultdict(dict) machine2_all_files = defaultdict(dict) machine1_lpdump = {} machine2_lpdump = {} # 收集数据 for folder_path, main_dict, all_dict, lpdump_dict in [ (folder1, machine1_main_data, machine1_all_files, machine1_lpdump), (folder2, machine2_main_data, machine2_all_files, machine2_lpdump) ]: print("处理目录: {}".format(folder_path)) try: # 先处理LPdump文件 lpdump_file = os.path.join(folder_path, '18_lpdump.txt') if os.path.exists(lpdump_file): print("解析LPdump文件: {}".format(lpdump_file)) lpdump_result = parse_lpdump_file(lpdump_file) if lpdump_result: lpdump_dict.update(lpdump_result) # 处理其他分区文件 for filename in os.listdir(folder_path): if not filename.endswith('.txt') or filename == '18_lpdump.txt': continue prefix = extract_file_prefix(filename) if not prefix or prefix == '01_' or prefix not in PARTITION_NAME_MAP: continue file_path = os.path.join(folder_path, filename) file_data = parse_du_file(file_path) if not file_data: print("警告: 文件无有效数据 - {}".format(file_path)) continue all_dict[filename] = file_data if is_main_partition_file(filename, prefix): print("解析主分区文件: {}".format(file_path)) main_dict[prefix] = file_data except OSError as e: return "目录访问错误: {}".format(str(e)) # 创建Excel工作簿 try: wb = xlwt.Workbook(encoding='utf-8') # 定义样式 header_style = xlwt.easyxf('font: bold on') title_style = xlwt.easyxf('font: bold on, height 280; align: vert centre') normal_style = xlwt.easyxf() added_style = xlwt.easyxf('pattern: pattern solid, fore_colour light_green;') removed_style = xlwt.easyxf('pattern: pattern solid, fore_colour rose;') summary_style = xlwt.easyxf('font: bold on, color blue;') wrap_style = xlwt.easyxf('align: wrap on, vert centre') # ====== 创建总览Sheet页 ====== ws_overview = wb.add_sheet('总览') print("创建总览Sheet页(使用LPdump数据)") current_row = 0 # 写入总览标题 ws_overview.write_merge(current_row, current_row, 0, 5, "存储使用总览(基于分区布局)", title_style) current_row += 2 # 空一行 # 写入文件夹名称 ws_overview.write(current_row, 1, folder1_name, header_style) ws_overview.write(current_row, 2, folder2_name, header_style) current_row += 1 # 写入表头 headers = ['分区', '总大小(MB)', '总大小(MB)', '差值(MB)', '标记', '备注(增大TOP3)'] for col, header in enumerate(headers): ws_overview.write(current_row, col, header, header_style) current_row += 1 # 获取所有分区名称(合并两个机器的分区) all_partitions = sorted( set(machine1_lpdump.keys()) | set(machine2_lpdump.keys()) | set(PARTITION_NAME_MAP.values()) ) # 按分区顺序处理数据 total_machine1 = 0.0 total_machine2 = 0.0 for partition_name in all_partitions: if partition_name == 'data': continue # 跳过data分区 # 获取LPdump中的分区大小 partition_total1 = machine1_lpdump.get(partition_name, 0.0) partition_total2 = machine2_lpdump.get(partition_name, 0.0) diff = partition_total1 - partition_total2 # 更新总计 total_machine1 += partition_total1 total_machine2 += partition_total2 # 确定标记样式 if diff > 0: mark = "增加" style = added_style elif diff < 0: mark = "减少" style = removed_style else: mark = "无变化" style = normal_style # 计算分区中增大的TOP3路径 top_notes = [] prefix_match = None # 查找对应的文件前缀 for pfx, name in PARTITION_NAME_MAP.items(): if name == partition_name: prefix_match = pfx break if prefix_match and diff >= 0: data1 = machine1_main_data.get(prefix_match, {}) data2 = machine2_main_data.get(prefix_match, {}) path_diffs = [] all_paths = set(data1.keys()) | set(data2.keys()) for path in all_paths: size1 = data1.get(path, 0.0) size2 = data2.get(path, 0.0) path_diff = size1 - size2 if path_diff > 0: # 只记录增大的路径 path_diffs.append((path, path_diff)) # 按增大值降序排序,取TOP3 path_diffs.sort(key=lambda x: x[1], reverse=True) for i, (path, diff_val) in enumerate(path_diffs[:3]): # 截断过长的路径名 display_path = path if len(path) <= 50 else "..." + path[-47:] top_notes.append("{}. {}: +{:.2f}MB".format(i+1, display_path, diff_val)) notes = "\n".join(top_notes) if top_notes else "无显著增大路径" # 写入行数据 ws_overview.write(current_row, 0, partition_name, style) ws_overview.write(current_row, 1, partition_total1, style) ws_overview.write(current_row, 2, partition_total2, style) ws_overview.write(current_row, 3, diff, style) ws_overview.write(current_row, 4, mark, style) ws_overview.write(current_row, 5, notes, wrap_style) current_row += 1 # 添加总计行 current_row += 1 total_diff = total_machine1 - total_machine2 if total_diff > 0: total_mark = "总增加" total_style = added_style elif total_diff < 0: total_mark = "总减少" total_style = removed_style else: total_mark = "无变化" total_style = normal_style ws_overview.write(current_row, 0, "总计", header_style) ws_overview.write(current_row, 1, total_machine1, header_style) ws_overview.write(current_row, 2, total_machine2, header_style) ws_overview.write(current_row, 3, total_diff, header_style) ws_overview.write(current_row, 4, total_mark, header_style) ws_overview.write(current_row, 5, "", header_style) # 设置列宽 ws_overview.col(0).width = 4000 # 分区列 ws_overview.col(1).width = 2500 # 大小1 ws_overview.col(2).width = 2500 # 大小2 ws_overview.col(3).width = 2500 # 差值 ws_overview.col(4).width = 2000 # 标记 ws_overview.col(5).width = 15000 # 备注(宽列) # ====== 为每个文件创建单独的Sheet页 ====== all_filenames = sorted(set(machine1_all_files.keys()) | set(machine2_all_files.keys())) for filename in all_filenames: prefix = extract_file_prefix(filename) if not prefix or prefix not in PARTITION_NAME_MAP: continue partition_name = PARTITION_NAME_MAP[prefix] sheet_name = filename.replace('.txt', '')[:31] # Excel名称长度限制 try: ws = wb.add_sheet(sheet_name) print("创建文件Sheet页: {}".format(sheet_name)) current_row = 0 ws.write_merge(current_row, current_row, 0, 5, "分区: {} - 文件: {}".format(partition_name, filename), title_style) current_row += 2 # 表头 ws.write(current_row, 0, "路径", header_style) ws.write(current_row, 1, "{}大小(M)".format(folder1_name), header_style) ws.write(current_row, 2, "路径", header_style) ws.write(current_row, 3, "{}大小(M)".format(folder2_name), header_style) ws.write(current_row, 4, "差值(M)", header_style) ws.write(current_row, 5, "标记", header_style) current_row += 1 # 获取文件数据 data1 = machine1_all_files.get(filename, {}) data2 = machine2_all_files.get(filename, {}) all_paths = sorted(set(data1.keys()) | set(data2.keys())) for path in all_paths: size1 = data1.get(path, 0.0) size2 = data2.get(path, 0.0) diff = size1 - size2 # 确定样式 if size1 > 0 and size2 == 0: mark, style = "新增", added_style elif size1 == 0 and size2 > 0: mark, style = "除去", removed_style elif diff > 0: mark, style = "增大", added_style elif diff < 0: mark, style = "减小", removed_style else: mark, style = "相同", normal_style # 写入数据 if size1 > 0: ws.write(current_row, 0, path, style) ws.write(current_row, 1, size1, style) else: ws.write(current_row, 0, "", style) ws.write(current_row, 1, "", style) if size2 > 0: ws.write(current_row, 2, path, style) ws.write(current_row, 3, size2, style) else: ws.write(current_row, 2, "", style) ws.write(current_row, 3, "", style) ws.write(current_row, 4, diff, style) ws.write(current_row, 5, mark, style) current_row += 1 # 文件汇总行 ws.write(current_row, 0, "文件汇总", header_style) ws.write(current_row, 1, sum(data1.values()), header_style) ws.write(current_row, 2, "", header_style) ws.write(current_row, 3, sum(data2.values()), header_style) ws.write(current_row, 4, sum(data1.values()) - sum(data2.values()), header_style) ws.write(current_row, 5, "", header_style) # 设置列宽 ws.col(0).width = 10000 ws.col(2).width = 10000 ws.col(4).width = 3000 ws.col(5).width = 2000 except Exception as e: print("创建Sheet页错误: {}".format(str(e))) # 保存工作簿 wb.save(output_xlsx) print("报告已生成: {}".format(output_xlsx)) return "成功生成对比报告: {}".format(output_xlsx) except Exception as e: return "生成Excel错误: {}".format(str(e)) if __name__ == "__main__": parser = argparse.ArgumentParser(description='生成双机存储对比报告') parser.add_argument('folder1', help='第一台设备数据目录') parser.add_argument('folder2', help='第二台设备数据目录') parser.add_argument('output', help='输出Excel文件路径') args = parser.parse_args() result = generate_dual_report(args.folder1, args.folder2, args.output) print(result) ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值