لديّ صفحات تنزيل الزاحف التي تعمل بالطاقة Gevent طوال الوقت. نمط Crawler Adopt Producer-Consumer ، الذي أطعم قائمة الانتظار مع بيانات مثل هذه {Method: Get ، url: xxxx ، other_info: yyyy}.
الآن أريد تجميع بعض الاستجابة في الملفات. المشكلة هي أنه لا يمكنني فتح وأكتب عندما ينتهي كل طلب ، وأن IO مكلفة والبيانات ليست بالترتيب الصحيح.
أفترض أنه قد أكون قد قمت بترقيم جميع الطلبات ، والاستجابة ذاكرة التخزين المؤقت بالترتيب ، وفتح خضراء لحلق وتجميع الملفات ، قد يكون رمز الزائفة مثل هذا:
max_chunk=1000
data=[]
def wait_and_assemble_file(): # a loop
while True:
if len(data)==28:
f= open('test.txt','a')
for d in data:
f.write(d)
f.close()
gevent.sleep(0)
def after_request(response, index): # Execute after every request ends
data[index]=response # every response is about 5-25k
هل هناك حل أفضل؟ هناك الآلاف من الطلبات المتزامنة ، وأشك في أن استخدام الذاكرة قد ينمو بسرعة كبيرة ، أو الكثير من الحلقة في وقت واحد ، أو شيء غير متوقع.
تحديث:
الرموز المذكورة أعلاه هي مجرد توضيح كيفية تخزين البيانات وكتابة الملفات. في الموقف العملي ، ربما يكون هناك 1 مائة حلقة لانتظار التقطير كاملة والكتابة إلى ملفات مختلفة.
update2
it ninja اقترح استخدام نظام قائمة الانتظار ، لذلك أكتب بديلاً باستخدام redis:
def after_request(response, session_id, total_block_count ,index): # Execute after every request ends
redis.lpush(session_id, msgpack.packb({'index':index, 'content':response})) # save data to redid
redis.incr(session_id+':count')
if redis.get(session_id+':count') == total_block_count: # which means all data blocks are prepared
save(session_name)
def save(session_name):
data_array=[]
texts = redis.lrange(session_name,0,-1)
redis.delete(session_name)
redis.delete(session_name+':count')
for t in texts:
_d = msgpack.unpackb(t)
index = _d['index']
content = _d['content']
data_array[index]=content
r= open(session_name+'.txt','w')
[r.write(i) for i in data_array]
r.close()
يبدو أفضل قليلاً ، لكنني أشك في ما إذا كان حفظ البيانات الكبيرة في Redis فكرة جيدة ، نأمل في المزيد من الاقتراحات!