【问题标题】:python use diskspace instead of RAM by no sufficient RAMpython使用磁盘空间而不是RAM,因为没有足够的RAM
【发布时间】:2016-09-21 14:04:59
【问题描述】:

考虑下面的python代码

with open(sys.argv[2], 'r') as fin, \
             open(sys.argv[3], 'w') as fout:
      reader = csv.DictReader(fin, delimiter='%s' % sys.argv[4])
      writer = csv.DictWriter(fout, reader.fieldnames, dialect='excel')
      writer.writeheader()
      writer.writerows(reader)

假设我们有一个大约 2GB 的大文件作为输入,而我们的系统只有 512MB RAM,这可能会导致错误 Memory Usage

有没有办法让我的代码使用磁盘空间而不是 RAM,即使这会使其变慢?或者这是一个操作系统问题,例如应该添加更多交换?

更新

上面的代码只是一个例子

考虑这个例子

with io.open(sys.argv[2], 'r', encoding='utf8', errors='ignore') as fin, \
     io.open(sys.argv[3], 'w', encoding='utf8', errors='ignore') as fout:
    rows = csv.DictReader(fin, delimiter='%s' % sys.argv[4])
    fout.write(json.dumps(list(rows), indent=4))

在使用json.dumps时,总是需要一次写入数据,如果要追加文件,则必须读取文件并追加数据并写入文件,类似这样

data = readjson(jsonfile)
data.append(newentry)
jsonfile.write(json.dumps(data))

使用生成器更新 2(惰性进化)

我想到了这个想法,但我不确定它是否会有所作为

def gen(list):
    for e in list:
        yield e

with open(sys.argv[2], 'r') as fin, \
             open(sys.argv[3], 'w') as fout:
      reader = csv.DictReader(fin, delimiter='%s' % sys.argv[4])
      writer = csv.DictWriter(fout, reader.fieldnames, dialect='excel')
      writer.writeheader()
      writer.writerows(gen(reader))

with open(sys.argv[2], 'r') as fin, \
     open(sys.argv[3], 'w') as fout:
    rows = csv.DictReader(fin, delimiter='%s' % sys.argv[4])
    # fout.write(json.dumps(gen(rows), indent=4)) -> cause error <generator object gen at 0x025BDDA0> is not JSON serializable
    fout.write(json.dumps(gen(list(rows)), indent=4))

【问题讨论】:

  • 天啊,那台电脑几岁了?
  • 如果您不想一次将一个结构全部读入内存,请使用该语言的惰性。如果 Python 支持任何惰性处理(可能通过流),您需要查找。
  • 只使用一个循环:for row in reader: writer.writerow(row).
  • @Carcigenicate 它不是计算机而是AWS EC2 Instance,我认为它的类型是t2.nano,我们也免费使用Heroku
  • @Eltorrooo 啊,这更有意义。

标签: python linux windows memory-management operating-system


【解决方案1】:

使用 json.dumps 时,您总是需要一次写入数据

不是真的。您确实应该对大数据采用流式处理方法。在这种情况下,类似于:

fout.write('[')
for ii, row in enumerate(rows):
    if ii != 0:
        fout.write(',\n')
    json.dump(row, fout, indent=4)
fout.write(']')

这样您可以一次写入一行,还可以节省将所有rows 放入您不需要的list 的开销。

【讨论】:

  • 使用json.dump 而不是json.dumps
  • @eryksun:好主意,我已经改变了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-15
  • 1970-01-01
  • 2015-03-10
  • 2017-08-07
  • 2014-09-27
  • 1970-01-01
相关资源
最近更新 更多