【问题标题】:How to return to top of for-loop when condition is False?条件为假时如何返回for循环顶部?
【发布时间】:2020-07-13 18:43:50
【问题描述】:

我已经为此苦苦挣扎了好几天,但没有成功进行研究。我正在尝试编写一个函数

  1. 遍历目录
  2. 打开一个匹配字符串模式的 excel 文件
  3. 打开文件并搜索特定工作表('importer')
  4. 将数据复制到 csv 并继续追加到 csv,直到所有文件完成。
  5. 我希望该函数忽略不包含“导入器”选项卡的文件,或者直接访问 FOR 循环中的下一个文件而不执行其余部分(“CSV 文件创建”)。
  6. 仅当文件名与模式匹配且“导入程序”工作表存在时才应创建文件。我觉得我很近,但只需要一点方向。
def append_all(input_directory):
    for file in os.listdir(input_directory):
        # Qualify if file exist
        if bool(re.search(pattern, file)) == True:
            # Join directory path name to file name
            in_fpath = os.path.join(input_directory, file)
            out_fpath = os.path.join(input_directory, 'history.csv')
            wrkbk = xlrd.open_workbook(in_fpath)
            if wrkbk.sheet_names() == 'importer':
                wrksht = wrkbk.sheet_by_name('importer')
                # Handling excel refresh date value to be used to populate csv file
                refresh_date_float = wrksht.cell_value(1, 4)
                refresh_date_value = xlrd.xldate_as_datetime(refresh_date_float, wrkbk.datemode).strftime(
                    '%Y/%m/%d %H:%M')
                # else:
                # continue

                # CSV FILE CREATION
                # Qualify if file exist. Default returns TRUE
                if os.path.isfile(out_fpath) == False:
                    # os.mkdir(output_directory)
                    # file will be created if it does not exist
                    with open(out_fpath, 'w', newline='') as csvfile:
                        wr = csv.writer(csvfile)
                        # start row index 3 to skip unecessary data
                        for rownum in range(3, wrksht.nrows):
                            # wr.writerow(wrksht.row_values(rownum) + list(refresh_date_value))
                            wr.writerow(list(wrksht.row_values(rownum)) + [refresh_date_value])
                            # Start append data
                else:
                    with open(out_fpath, 'a', newline='') as csvfile:
                        wr = csv.writer(csvfile)
                        # start row index 4 to skip header row
                        for rownum in range(4, wrksht.nrows):
                            # wr.writerow(wrksht.row_values(rownum)  + list(refresh_date_value))
                            wr.writerow(list(wrksht.row_values(rownum)) + [refresh_date_value])


csvfile.close()
print('process complete')

【问题讨论】:

  • 返回for 块顶部的一种常规方式是continue。我看到您在代码中注释掉了 continue。它没有做你想让它做的事情吗?如果没有,它做了什么,你想让它做什么?
  • .sheet_names() 返回一个列表 - wrkbk.sheet_names() == 'importer' 将始终 False。你应该使用in or not in
  • @Kevin 当我添加 'else: continue' 时,它只是运行没有错误,但没有在目录中创建文件。我认为要么我没有正确处理错误场景,要么我的缩进是错误的?
  • @wwii 也许这就是我没有看到写入目录的文件的原因。我仍然有点不清楚如何在列表对象中使用“in”或“not in”。会不会写成 '''if 'importer' in wrkbk.sheet_names():'''?
  • if 'importer' in wrkbk.sheet_names(): - 是的。 ...Check if something is (not) in a list in Python

标签: python loops for-loop nested-loops


【解决方案1】:
  • 使用pathlib 模块中的.rglob 查找具有指定模式的文件。
    • 这就像调用Path.glob() 并在给定的相对模式前面添加'**/'
    • pathlib 模块提供了表示文件系统路径的类,这些类具有适用于不同操作系统的语义。
  • try-except 块内使用sheet_name 参数会更容易使用pandas.read_excel
    • try-except 块将尝试加载具有工作表名称的文件。如果工作表不存在,则会发生异常。在这种情况下,如果出现异常,脚本将转到下一个文件。
  • 使用 pandas.concat 将所有文件合并到一个数据帧中,然后使用 .to_csv 将其保存到 csv。
from pathlib import Path
import pandas as pd

p = Path('c:/.../path_to_files')  # path to files

files = list(p.rglob('*.xlsx'))  # get all xlsx files that match the pattern

list_of_dataframes = list()  # list to add dataframe to
for file in files:
    try:
        list_of_dataframes.append(pd.read_excel(file, sheet_name='importer'))  # add dataframe from Excel file to list
    except XLRDError:  # exception because there's not importer worksheet
        print(f'{file} did have the "importer" worksheet')
        
df = pd.concat(list_of_dataframes)  # combine the dataframes from all the files

df.to_csv('my_combined_files.csv', index=False)  # save to a csv

作为一个函数

def create_csv_from_multiple_xlsx_files(path_to_files: str, filename_pattern: str, save_name: str):
    
    p = Path(path_to_files)  # convert to pathlib object

    files = list(p.rglob(filename_pattern))  # get all xlsx files that match the pattern

    list_of_dataframes = list()  # list to add dataframe to
    for file in files:
        try:
            list_of_dataframes.append(pd.read_excel(file, sheet_name='importer'))  # add dataframe from Excel file to list
        except XLRDError:  # exception because there's not importer worksheet
            print(f'{file} did have the "importer" worksheet')

    df = pd.concat(list_of_dataframes)  # combine the dataframes from all the files

    df.to_csv(f'{save_name}.csv', index=False)  # save to a csv
    
    
top_level_file_dir = 'c:/.../path_to_files'  # path to files
pattern = '*.xlsx'  # filename pattern
csv_file_name = 'my_combined_files'
create_csv_from_multiple_xlsx_files(top_level_file_dir, pattern, csv_file_name)  # call function

【讨论】:

    猜你喜欢
    • 2017-07-23
    • 1970-01-01
    • 2011-04-25
    • 1970-01-01
    • 1970-01-01
    • 2015-10-26
    • 2015-07-01
    • 2017-01-30
    • 1970-01-01
    相关资源
    最近更新 更多