[英]How do I wait for a subprocess to finish, store it's output and add a prefix (without a new line) to the output?
[英]How do I continue iterating without having to wait output to finish?
import sqlite3
conn = sqlite3.connect('output.db')
count = 0
items = []
for item in InfStream: # assume I have an infinite stream
items.append((item,))
count += 1
if count == 10000:
conn.executemany("INSERT INTO table VALUES (?)", items)
conn.commit()
items = []
在此Python代码中,我有一个来自API的长度未知的流,称为InfStream,我想将流中的项目插入到sqlite数据库的表中。 在这种情况下,我首先创建一个包含10,000个项目的列表,然后使用executemany将其插入数据库。 这大约需要1个小时。 但是,代码有问题,当executemany运行时,我必须等待约15秒才能完成。 在我的情况下,这是不可接受的,因为我需要继续从流中获取该项目,否则,如果我延迟太长时间,它将被断开。
我希望在同时运行executemany的同时继续循环。 有可能这样做吗?
nb。 输入比写入慢得多。 输入10,000个项目大约需要1个小时,而输出仅需15秒。
这是一个经典的生产者-消费者问题 ,最好使用Queue处理。
在这种情况下,生产者是您的InfStream,而消费者是您的for块中的所有内容。
将您的顺序代码转换为多线程生产者-消费者模型并使用Queue在线程之间分配数据将是很直接的
考虑你的代码
import sqlite3
conn = sqlite3.connect('output.db')
count = 0
items = []
for item in InfStream: # assume I have an infinite stream
items.append((item,))
count += 1
if count == 10000:
conn.executemany("INSERT INTO table VALUES (?)", items)
conn.commit()
items = []
创建一个Consumer函数 ,以使用数据
def consumer(q):
def helper():
while True:
items = [(q.get(),) for _ in range(10000)]
conn.executemany("INSERT INTO table VALUES (?)", items)
conn.commit()
return helper
和生产者功能来生产它,直到无限
def producer():
q = Queue()
t = Thread(target=consumer(q))
t.daemon = True
t.start()
for item in InfStream:
q.put(item)
q.task_done()
针对注释的补充说明
如果消费者不能跟上生产者的步伐
Span Multiple Consumer将数据放入速度更快的IO设备中,然后将其刷新到数据库中。 使计数可配置和动态。
听起来好像executemany
在IO上被阻止了,所以threading
在这里实际上可能会有所帮助,所以我会先尝试一下。 特别是,创建一个单独的线程,该线程将简单地对第一个线程扔到共享队列上的数据调用executemany
。 然后,第一次读取可以继续读取,而第二个线程执行executemany
。 正如另一个答案所指出的,这是一个生产者-消费者问题。
如果那不能解决问题,请切换到multiprocessing
。
请注意,如果输入的流入速度比在第二个线程或进程中写入的速度快,那么这两种解决方案都不会起作用,因为填满内存的速度要快于清空内存的速度。 在这种情况下,无论如何,您都必须限制输入的读取率。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.