Python脚本使用说明:从CSV提取指定列数据
脚本目标
本Python脚本旨在帮助您从CSV(逗号分隔值)文件中提取特定列的数据。您可以指定要提取哪一列,是否跳过CSV文件的第一行(通常是表头),并且可以选择输出所有行、前N行、后N行或指定范围的行。所有最终输出的数据都将是字符串格式,并以元组(tuple)的形式呈现,例如 ('数据1', '数据2', '数据3')。
如何使用
-
保存脚本:
- 将之前提供的最新Python代码复制到一个文本文件中。
- 将该文件保存为
.py结尾的Python文件,例如extract_csv_column_v2.py。
-
准备您的CSV文件:
- 确保您知道要处理的CSV文件的完整路径(例如
C:\Users\您的用户名\Documents\data.csv或者/home/user/data.csv)。 - 确认您要提取的是第几列的数据。
- 确保您知道要处理的CSV文件的完整路径(例如
-
运行脚本:
- 打开您的计算机的终端(在Windows上可能是命令提示符
cmd或 PowerShell,在macOS或Linux上是Terminal)。 - 使用
cd命令切换到您保存Python脚本的目录。例如,如果您保存在Documents文件夹下,可以输入:cd Documents - 然后运行脚本,输入:
(请将python extract_csv_column_v2.pyextract_csv_column_v2.py替换为您实际保存的文件名)。
- 打开您的计算机的终端(在Windows上可能是命令提示符
-
按照提示操作:
脚本运行时,会依次向您提问:-
"请输入您的CSV文件路径 (Enter the path to your CSV file):"
- 在这里输入您的CSV文件的完整路径,然后按回车键。
- 示例:
my_data.csv(如果文件在脚本同一目录下) 或/path/to/your/file.csv
-
"请输入要提取的列号 (例如,1代表第一列) (Enter the column number to extract, e.g., 1 for the first column):"
- 输入您想要提取数据的是第几列。请注意,这里的列号是从
1开始计数的。例如,要提取第一列,请输入1;要提取第二列,请输入2,以此类推。然后按回车键。
- 输入您想要提取数据的是第几列。请注意,这里的列号是从
-
"您的CSV文件是否有需要跳过的表头行? (yes/no) (Does your CSV file have a header row to skip? (yes/no)):"
- 如果您的CSV文件的第一行是列名或标题(即表头),并且您不希望将表头包含在最终的输出数据中,请输入
yes或y。 - 如果您的CSV文件没有表头,或者您希望将第一行也作为数据提取出来,请输入
no或n。 - 然后按回车键。
- 如果您的CSV文件的第一行是列名或标题(即表头),并且您不希望将表头包含在最终的输出数据中,请输入
-
行选择选项提示:
脚本会显示以下行选择选项:行选择选项 (Row selection options): 1. 所有行 (All rows - default) 2. 前 N 行 (First N rows) 3. 后 N 行 (Last N rows) 4. 指定范围的行 (e.g., 100-500) (A specific range of rows)- "请选择行选择选项 (1/2/3/4,或直接按 Enter 选择 '所有行'):"
- 输入选项编号 (
1,2,3,4) 或直接按 Enter 键选择默认的“所有行”。
- 输入选项编号 (
- "请选择行选择选项 (1/2/3/4,或直接按 Enter 选择 '所有行'):"
-
根据行选择的进一步提示:
- 如果选择
1(所有行) 或直接按 Enter:不会有更多关于行选择的提问。 - 如果选择
2(前 N 行):- 会提示:"请输入要提取的前 N 行中的 N 值:"
- 输入一个正整数 N。
- 如果选择
3(后 N 行):- 会提示:"请输入要提取的后 N 行中的 N 值:"
- 输入一个正整数 N。
- 如果选择
4(指定范围的行):- 会提示(提示文本会根据您之前是否选择跳过表头而略有不同):
- (如果不跳过表头): "请输入行范围 (例如 100-500,1基准,包含首尾):"
- (如果跳过表头): "请输入数据行范围 (例如 100-500,1基准,包含首尾,指跳过表头后的数据行):"
- 输入行范围,格式为
开始行-结束行(例如100-500)。这里的行号是 1基准 的,并且 包含 开始行和结束行。 - 重要:如果选择了跳过表头,那么这里输入的行号指的是数据行的行号(即表头之后的第一行数据为第1行,第二行数据为第2行,以此类推)。
- 会提示(提示文本会根据您之前是否选择跳过表头而略有不同):
- 如果选择
-
-
查看输出:
- 脚本会读取CSV文件,根据您的选择处理数据,然后会在终端打印出提取到的数据。
- 输出的格式将是一个元组 (tuple),其中每个元素都是字符串类型。例如:
或者,如果提取的是文本:提取的数据 (元组格式,所有元素为字符串): (Extracted data as a tuple of strings): ('144173556479295488', '144173858159984640', '144190726925385728')提取的数据 (元组格式,所有元素为字符串): (Extracted data as a tuple of strings): ('张三', '李四', '王五')
注意事项与错误处理
- 文件路径:确保提供的CSV文件路径是正确的,否则脚本会提示文件未找到。
- 列号:如果输入的列号超出了CSV文件实际的列数,对于短于该列号的行,脚本会打印警告(包含具体的CSV文件行号和行内容),并在该数据项的位置使用空字符串
''。 - 行选择与数据量:
- 前 N 行 / 后 N 行:如果您请求的 N 值大于实际可用的数据行数,脚本将返回所有可用的数据行(例如,请求前100行,但数据只有50行,则返回这50行)。
- 指定范围的行:
- 您输入的行号是相对于数据行(如果跳过表头)或所有行(如果不跳过表头)的1基准索引。
- 如果指定的开始行号超出了总数据行数,输出将为空。
- 如果指定的范围部分或全部超出了实际数据行,脚本会尝试提取范围内有效的部分,并可能给出警告。
- 如果开始行号大于结束行号,脚本会提示错误并要求重新输入。
- 编码:脚本默认使用
utf-8编码读取CSV文件。如果您的CSV文件使用其他编码(如gbk),您可能需要修改脚本中的encoding='utf-8'部分。 - 空文件/空数据:
- 如果CSV文件为空,或者在跳过表头(如果选择)后没有数据,脚本将输出一个空元组
()并给出相应提示。 - 如果指定的列本身在所有选定行中均为空或因行太短而无法提取,对应位置也将是空字符串。
- 如果CSV文件为空,或者在跳过表头(如果选择)后没有数据,脚本将输出一个空元组
- 输入验证:脚本会对列号、N值、行范围等输入进行基本的验证,如要求正整数、正确的范围格式等。
脚本Python代码:
import csv
def extract_column_to_tuple_of_strings():
"""
Prompts the user for CSV file details, extracts a specified column
with options to limit rows, and prints it as a tuple of strings.
"""
file_path = input("请输入您的CSV文件路径 (Enter the path to your CSV file): ")
while True:
try:
column_input_str = input("请输入要提取的列号 (例如,1代表第一列) (Enter the column number to extract, e.g., 1 for the first column): ")
column_index = int(column_input_str) - 1
if column_index < 0:
print("列号必须是大于等于1的整数。请重新输入。(Column number must be 1 or greater. Please try again.)")
continue
break
except ValueError:
print("输入无效。请输入一个整数作为列号。(Invalid input. Please enter a whole number for the column.)")
skip_header = False
while True:
include_header_str = input("您的CSV文件是否有需要跳过的表头行? (yes/no) (Does your CSV file have a header row to skip? (yes/no)): ").lower()
if include_header_str in ['yes', 'y']:
skip_header = True
break
elif include_header_str in ['no', 'n']:
skip_header = False
break
else:
print("输入无效。请输入 'yes' 或 'no'。(Invalid input. Please enter 'yes' or 'no'.)")
# 行选择逻辑
row_limit_mode = "all"
limit_n = 0
limit_start_row = 0 # 1-based for user input
limit_end_row = 0 # 1-based for user input
print("\n行选择选项 (Row selection options):")
print("1. 所有行 (All rows - default)")
print("2. 前 N 行 (First N rows)")
print("3. 后 N 行 (Last N rows)")
print("4. 指定范围的行 (e.g., 100-500) (A specific range of rows)")
while True:
choice = input("请选择行选择选项 (1/2/3/4,或直接按 Enter 选择 '所有行'): ").strip().lower()
if choice == '1' or choice == 'all' or not choice:
row_limit_mode = "all"
break
elif choice == '2' or choice == 'first':
row_limit_mode = "first"
while True:
try:
limit_n_str = input("请输入要提取的前 N 行中的 N 值: ")
limit_n = int(limit_n_str)
if limit_n <= 0:
print("N 必须是一个正整数。(N must be a positive integer.)")
continue
break
except ValueError:
print("输入无效。请输入一个整数作为 N 值。(Invalid input. Please enter a whole number for N.)")
break
elif choice == '3' or choice == 'last':
row_limit_mode = "last"
while True:
try:
limit_n_str = input("请输入要提取的后 N 行中的 N 值: ")
limit_n = int(limit_n_str)
if limit_n <= 0:
print("N 必须是一个正整数。(N must be a positive integer.)")
continue
break
except ValueError:
print("输入无效。请输入一个整数作为 N 值。(Invalid input. Please enter a whole number for N.)")
break
elif choice == '4' or choice == 'range':
row_limit_mode = "range"
range_prompt = "请输入行范围 (例如 100-500,1基准,包含首尾): "
if skip_header:
range_prompt = "请输入数据行范围 (例如 100-500,1基准,包含首尾,指跳过表头后的数据行): "
while True:
try:
range_str = input(range_prompt)
parts = range_str.split('-')
if len(parts) != 2:
raise ValueError("范围必须是 '开始行-结束行' 的格式。(Range must be in format start-end.)")
limit_start_row = int(parts[0].strip())
limit_end_row = int(parts[1].strip())
if limit_start_row <= 0 or limit_end_row <= 0:
print("行号必须是正整数。(Row numbers must be positive.)")
continue
if limit_start_row > limit_end_row:
print("开始行号不能大于结束行号。(Start row cannot be greater than end row.)")
continue
break
except ValueError as e:
print(f"输入无效: {e} 请使用 '开始行-结束行' 格式并输入数字 (e.g., 100-500)。(Invalid input: {e}. Please use format 'start-end' with numbers (e.g., 100-500).)")
break
else:
print("选择无效。请输入 1, 2, 3, 4, 或 'all' (或直接按 Enter)。(Invalid choice. Please enter 1, 2, 3, 4, or 'all' (or press Enter).)")
all_column_data = []
try:
with open(file_path, mode='r', newline='', encoding='utf-8') as csvfile:
reader = csv.reader(csvfile)
header_skipped_once = False
if skip_header:
try:
next(reader) # 跳过表头行
header_skipped_once = True
except StopIteration:
print("警告: CSV文件为空或仅包含表头。(Warning: CSV file is empty or only contains a header.)")
# 读取指定列的所有(潜在)数据行
for row in reader:
current_csv_line_num = reader.line_num # 获取当前在CSV文件中的物理行号
try:
all_column_data.append(str(row[column_index]))
except IndexError:
# column_input_str 是用户输入的1基准列号
print(f"警告: CSV文件第 {current_csv_line_num} 行, 内容 '{','.join(row)}', 对于列号 {column_input_str} 来说太短。将为此项使用空字符串。")
print(f"(Warning: CSV line {current_csv_line_num}, Row content '{','.join(row)}', is too short for column index {column_input_str}. Using empty string for this item.)")
all_column_data.append('') # 如果行太短,添加空字符串
# 根据用户的选择应用行限制
final_data_to_output = []
if not all_column_data:
if not header_skipped_once and skip_header: # 文件是空的,并且尝试跳过表头但失败了
pass # 警告已在上面打印
elif header_skipped_once and not all_column_data: # 文件只有表头
print("在跳过表头后,指定列没有数据。(No data found in the specified column after skipping the header.)")
else: # 文件本身就没数据(或者指定列没数据,但通常是前者)
print("在指定列或文件中未找到数据。(No data found in the specified column or file.)")
elif row_limit_mode == "all":
final_data_to_output = all_column_data
elif row_limit_mode == "first":
final_data_to_output = all_column_data[:limit_n]
elif row_limit_mode == "last":
final_data_to_output = all_column_data[-limit_n:]
elif row_limit_mode == "range":
# 用户输入的 limit_start_row 和 limit_end_row 是1基准的
# Python列表切片是0基准的,且不包含尾部索引
# 所以,[M-1 : N] 会提取第 M 项到第 N 项
start_idx = limit_start_row - 1
end_idx = limit_end_row
if start_idx >= len(all_column_data):
print(f"警告: 开始行 {limit_start_row} 超出了数据总行数 ({len(all_column_data)} 行)。输出将为空。")
print(f"(Warning: Start row {limit_start_row} is beyond the end of the data ({len(all_column_data)} data rows). Output will be empty.)")
final_data_to_output = []
else:
final_data_to_output = all_column_data[start_idx:end_idx]
if not final_data_to_output and start_idx < end_idx: # 检查范围是否有效但结果为空
# 例如,数据共5行,用户请求6-10行
if start_idx < len(all_column_data) and end_idx > len(all_column_data):
print(f"警告: 指定范围 {limit_start_row}-{limit_end_row} 部分超出数据行 ({len(all_column_data)} 行),仅输出范围内有效部分。")
elif start_idx >= len(all_column_data): # 这种情况已在上面处理
pass
else: # 例如,请求 100-200 行,但数据只有 50 行
print(f"警告: 指定范围 {limit_start_row}-{limit_end_row} 没有从可用的 {len(all_column_data)} 数据行中获取到数据。")
print(f"(Warning: The specified range {limit_start_row}-{limit_end_row} resulted in no data from the available {len(all_column_data)} data rows.)")
output_tuple = tuple(final_data_to_output)
print("\n提取的数据 (元组格式,所有元素为字符串):")
print("(Extracted data as a tuple of strings):")
print(output_tuple)
except FileNotFoundError:
print(f"错误: 文件 '{file_path}' 未找到。(Error: The file '{file_path}' was not found.)")
except Exception as e:
print(f"发生未知错误: {e} (An unexpected error occurred: {e})")
if __name__ == "__main__":
extract_column_to_tuple_of_strings()