【问题标题】:How to add another loop to a Python nested loop?如何向 Python 嵌套循环添加另一个循环?
【发布时间】:2020-12-22 20:24:30
【问题描述】:

已编辑

我是 Python 新手,在向嵌套循环 Python 代码添加循环时遇到问题。 在我的 Windows 7 机器上使用 Python 3.8。

代码在运行一次时执行:它从多个 CSV 文件中逐行读取,并且逐个 CSV 文件读取,并使用每一行的数据(在给定范围内)运行函数,直到没有 CSV左侧文件,每个 CSV 文件有 4 列,所有 CSV 文件各有一个标题。 每行读取之间有几秒钟的延迟。

由于该代码仅供一次性使用,当您再次运行该代码时,它会读取相同的行,而不会循环读取其他行。

所以我想向它添加另一个循环,因此每次您以某种方式运行文件时,它都会记住使用的最后一行并从下一行开始。 所以假设它已被设置为 2 行的范围:

第一次运行:使用第 1 行和第 2 行运行函数 第二次运行:使用第 3 行和第 4 行运行函数,以此类推

感谢您的帮助。

CSV 示例

img_url,desc_1 title_1,link_1
site.com/image22.jpg;someTitle;description1;site1.com
site.com/image32.jpg;someTitle;description2;site2.com
site.com/image44.jpg;someTitle;description3;site3.com

这是我的工作代码:

from abc.zzz  import xyz
path_id_map = [
    {'path':'file1.csv', 'id': '12345678'},
    {'path':'file2.csv', 'id': '44556677'}
    {'path':'file3.csv', 'id': '33377799'}
    {'path':'file4.csv', 'id': '66221144'}]
s_id = None

for pair in path_id_map:
    with open(pair['path'], 'r') as f:
        next(f)  # skip first header line
        for _ in range(1, 3):      
            line = next(f)
            img_url, title_1, desc_1, link_1 = map(str.strip, line.split(';'))
            zzz.func1(img_url=img_url, title_1=title_1, desc_1=desc_1, 
                      link_1=link_1, B_id=B_id=pair['id'], s_id=s_id)
            time.sleep(25)

**** 更新****

在寻找解决方案几天后,已发布代码(更新 2): 但它有一个大问题。

只有在使用打印功能时,它才能以我想要的方式工作,

我采用了我的函数,但是,当它第二次或更多次运行时,它不会循环到下一行,(但它只会在最后一个 CSV 文件上正确循环),

代码的作者无法更正他的代码,我不知道它有什么问题。

我检查了 CSV 文件并使用打印功能对其进行了测试,它们都可以。

也许有人帮助解决问题或完全解决问题。

【问题讨论】:

  • 所以基本上你想保存一些关于 csv 文件的元数据。 IE。读取 csv 后,您将在 csv 中添加一行,然后在另一个文件中保存您离开的行,以便您可以再次从该行开始。这就是你想要的吗?
  • 感谢您的回复,我打算逐行使用 CSV 文件数量中的所有数据,按给定的行范围和每天的运行次数,我不想让宝宝坐着,我不想'不知道是否需要写入数据 csv 文件,我不想弄乱数据 csv 文件,我想以某种方式将最后使用的行(索引)记录到文本文件中,并且每次文件运行时检查首先这个文本文件,对于最后一行索引号,添加一个(最后一行索引号+1)作为新的行号开始读取csv文件。
  • 我不能 100% 确定你到底想要什么,所以我不能提供一个很好的代码示例,但我建议阅读这篇关于 saving and loading to a JSON file 的文章。 JSON 基本上只是 python 列表和字典。因此,您可以很容易地从文件中保存和加载字典。非常适合在这些情况下保存和加载值。

标签: python python-3.x nested-loops


【解决方案1】:

您好,我希望我已经理解您的要求。如果您根据自己的情况稍微调整一下,我认为下面的代码可能会指导您。您可以将最后一行的编号存储到文本文件中。我还假设使用分号作为分隔符。

更新 1

好的,我想我想出了解决您问题的方法,希望如此。运行它的唯一先决条件是拥有一个文本文件,其中包含您希望在 first 运行时开始的行数(例如 1)。

# define function
import csv
import time
import subprocess
import os
import itertools

# txt file that contains the number of line to start the next time
dir_txt = './'
fname_txt = 'number_of_last_line.txt'
path = os.path.join(dir_txt, fname_txt)
# assign line number to variable after reading relevant txt
with open(path, 'r', newline='') as f:
    n = int(f.read())

# define path of csv file
fpath = './file1.csv'

# open csv file
with open(fpath, 'r', newline='') as csvfile:

    csv_reader = csv.reader(csvfile, delimiter=';')
    
    # Iterate every row of csv. csv_reader row number starts from 1,
    # csv_reader generator starts from 0
    for row in itertools.islice(csv_reader, n, n+3):
        print('row {0} contains {1}'.format(csv_reader.line_num, row))
        time.sleep(3)

# Store the number of line to start the next time
n = csv_reader.line_num + 1
# Bash (or cmd) command execution, option. You can do this with python also
sh_command = 'echo {0} > {1}'.format(csv_reader.line_num, path)
subprocess.run(sh_command, shell=True)

更新 2

这是一个使用@Error 输入的代码对多个文件工作的修订 - 语法悔恨。您需要做的第一件事是打开 metadata.json 文件并插入要开始每个文件的行数,仅限第一次运行。您还需要根据自己的情况更改文件目录。

# define function
def get_json_metadata(json_fpath):
    """Read json file
    Args:
        json_fpath -- string (filepath)
    Returns:
        json_list -- list"""

    with open(json_fpath, mode='r') as json_file:
        json_str = json_file.read()
        json_list = json.loads(json_str)
    return json_list

# Imports
import csv, json
import time
import os
import itertools

# json file that contains the number of line to start the next time
dir_json = './'
fname_json = 'metadata.json'
json_fpath = os.path.join(dir_json, fname_json)
# csv filenames, IDs and number of row to start reading are extracted
path_id_map = get_json_metadata(json_fpath)

# iterate over csvfiles
for nfile in path_id_map:
    print('\n------ Reading {} ------\n'.format(nfile['path']))
    with open(nfile['path'], 'r', newline='') as csvfile:

        csv_reader = csv.reader(csvfile, delimiter=';')
        
        # Iterate every row of csv. csv_reader row number starts from 1,
        # csv_reader generator starts from 0
        for row in itertools.islice(csv_reader, nfile['nrow'], nfile['nrow']+5):
            # skip empty line (list)
            if not row:
                continue
            # assign values to variables
            img_url, title_1, desc_1, link_1 = row
            B_id = nfile['id']

            print('row {0} contains {1}'.format(csv_reader.line_num, row))
            time.sleep(3)

    # Store the number of line to start the next time
    nfile['nrow'] = csv_reader.line_num

with open(json_fpath, mode='w') as json_file:
    json_str = json.dumps(path_id_map, indent=4)
    json_file.write(json_str)

metadata.json 格式应该是这样的:

[
    {
        "path": "file1.csv",
        "id": "12345678",
        "nrow": 1
    },
    {
        "path": "file2.csv",
        "id": "44556677",
        "nrow": 1
    },
    {
        "path": "file3.csv",
        "id": "33377799",
        "nrow": 1
    },
    {
        "path": "file4.csv",
        "id": "66221144",
        "nrow": 1
    }
]

【讨论】:

  • 感谢您的回复;我无法采用您的代码,因为您注意到在我的代码中我使用了多个 csv 文件并且 csv 文件包含多个列,所以由于我是 Python 新手,所以我无法弄清楚如何将它应用到我的代码中。
  • @Dave99 我刚刚对多个文件进行了修订,并将 JSON 元数据文件用作错误 - 建议语法悔恨
  • Kostas VI,感谢更新的代码,新代码工作正常,打印功能完全符合我的要求,但是当我用我的函数 zzz.func1('row {0} contains {1}'.format(csv_reader.line_num, row)) 替换打印时,我收到以下错误:@ 987654325@ 和 No value for argument 'img_url' in unbound method call 所以代码无法识别我函数中的参数。 B_id 值在 json 文件中作为 id,img_url 在 CSV 文件中。我确实将 id (B_id) 值放入了 CSV 文件(添加了另一列),但仍然无法正常工作。
  • 嗨@Dave99 查看代码。我做了另一个修改来解决你的问题
  • 感谢 Kostas VI,对于更新的代码,我应用了更新的代码,我仍然得到同样的错误:func1() missing 2 required positional arguments: 'B_id' and 'img_url'
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-10-12
  • 1970-01-01
  • 2022-01-08
  • 2021-05-26
  • 2014-11-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多