【问题标题】:python with open for loop带有开放for循环的python
【发布时间】:2018-01-10 17:36:20
【问题描述】:

我有一个大小合适的网页抓取脚本,其中包含 25K+ url 的输入到一个单独的页面抓取函数中,该函数在所有 url 中运行一个 for 循环。在 for 循环结束时,它将结果写入 csv。 目前,我有这个代码:

if link == url[0]:
        # Creating the file and writing headers with the first entry and closing after
        # the first entry to go from write mode to append mode
        with open(file_Name, 'w') as f:
            stats_df.to_csv(f)
            record_Counter = record_Counter + 1
            print ('Two entries for one game recorded.  Counter = '  + str(record_Counter))
    elif link == url[1]:
        # Opening the file in append mode and keeping it open for the majority of the loop
        # and writing with no headers
        f = open(file_Name, mode = 'a') 
        stats_df.to_csv(f, header=False)
        record_Counter = record_Counter + 1
        print ('Two entries for one game recorded.  Counter = '  + str(record_Counter))
    elif link == url[-1]:
        # Writing the final entry of this page and closing the file
        stats_df.to_csv(f, header=False)
        record_Counter = record_Counter + 1
        print ('Two entries for one game recorded.  Counter = '  + str(record_Counter))
        f.close()
    else:
        # Writing all entries in between
        stats_df.to_csv(f, header=False)
        record_Counter = record_Counter + 1
        print ('Two entries for one game recorded.  Counter = '  + str(record_Counter))

以前,我有这个:

if link == url[0]:
        with open(file_Name, 'w') as f:
            stats_df.to_csv(f)
            record_Counter = record_Counter + 1
            print ('Two entries for one game recorded.  Counter = '  + str(record_Counter))
else:
        with open(file_Name, 'a') as f:
            stats_df.to_csv(f)
            record_Counter = record_Counter + 1
            print ('Two entries for one game recorded.  Counter = '  + str(record_Counter))

我对更简单的代码的担忧是我打开和关闭 csv 文件 25K 次,这会减慢我的运行时间。我目前担心的是在打开 f 的异常情况下内存损坏的问题。

我是否有理由担心我的任何一个问题?感谢您的宝贵时间。

【问题讨论】:

  • 代码已损坏(标识) - 您的来源中就是这种情况?
  • 我会选择第二种方法,获得部分结果似乎比获得第一种方法更好。重新开始抓取也更容易 - 只需使用 25k 网址中的第 n 个条目重新开始。
  • 纯粹出于兴趣-。我每天都会看到几个网络抓取 python 线程,我总是问自己:“为什么”?
  • Patrick:不,代码在我的实际代码中工作并且当前正在运行。在将其放入代码块的 SO 格式中时,我可能犯了一些格式错误。
  • “打开和关闭 csv 文件 25K 次”似乎很简单……您是否真的对此进行了基准测试以查看它是否存在某种瓶颈?我会选择第二种形式,如果您的代码运行速度太慢,那么 profile 它会确定上述是否真的是一个问题。这有点过早的优化。

标签: python csv for-loop file-io


【解决方案1】:

真正的问题是程序员在错误的地方和错误的时间花费了太多时间来担心效率;过早的优化是编程中万恶之源(或至少是大部分)。--Donald Knuth

我在 1982 年或 83 年开始在分时迷你电脑上学习编程。东西慢慢地跑了。记忆很紧。因此,我太担心有多少内存/操作/等。我的代码使用。放下这件事很难。

你说:

我对更简单的代码的担心是我打开和关闭 csv 文件 25K 次,这会减慢我的运行时间。

当然是。但明显吗?应用程序的时间敏感性如何?如果需要额外运行 60 秒,会有什么影响?

另一方面:

我目前担心的是在打开 f 的异常时内存损坏的问题。

你这是什么意思?

如果遇到异常并且程序关闭,Python 会自行清理。如果您担心有人做坏事,它可能不会在退出时清除所有内存,但异常处理的全部意义在于以安全且一致的方式处理异常。

我可能对此非常错误,但是我阅读这段代码的方式:

elif link == url[1]:
    # Opening the file in append mode and keeping it open for the majority of the loop
    # and writing with no headers
    f = open(file_Name, mode = 'a') 
    stats_df.to_csv(f, header=False)
    record_Counter = record_Counter + 1
    print ('Two entries for one game recorded.  Counter = '  + str(record_Counter))

尝试每次通过循环打开 file_name 并调用文件句柄 f。我不知道虚拟机内部会发生什么,但是(a)您每次都关闭并重新打开文件,或者(ii)您发现文件已经打开并且只是重用 f.我不知道这比仅仅打开附加文件并将数据爆破到它有多少效率。

IMO 我认为这种规模的速度差异不值得。

另一方面,Knuth 也说:

程序员会浪费大量时间来思考或担心程序中非关键部分的速度,而在考虑调试和维护时,这些提高效率的尝试实际上会产生强烈的负面影响。我们应该忘记小的效率,比如大约 97% 的时间:过早优化是万恶之源。然而,我们不应该放弃那关键的 3% 的机会。

【讨论】:

  • 我总是赞成 Knuth 的智慧。我大约在 3 年前才开始编程,但我仍然发现自己痴迷于代码的琐碎方面。诸如努力在数据结构上一次完成所有事情的事情,当简单地执行两次时,代码的可读性和直接性提高了 10 倍,对运行时的影响可以忽略不计。
猜你喜欢
  • 2019-01-30
  • 2021-08-21
  • 2013-01-25
  • 2013-10-08
  • 1970-01-01
  • 1970-01-01
  • 2012-12-12
  • 1970-01-01
  • 2014-06-02
相关资源
最近更新 更多