بث سجلات CSV متعددة الأسطر باستخدام Python Requests وcsv.reader
بث استجابة تمر عبر وكيل إلى csv.reader والحفاظ على حدود السجلات بدل تقسيم كل سطر فعلي عند الفاصل.
يتيح stream=True بدء المعالجة قبل اكتمال تنزيل جسم استجابة تمر عبر وكيل. وبالنسبة إلى CSV، مرِّر مكرِّرًا لأسطر نصية إلى csv.reader حتى تبقى الفواصل الواقعة بين علامات الاقتباس والسجلات متعددة الأسطر بيانات CSV.
لملف UTF-8 توضيحي يستخدم الفواصل المنقوطة:
import csv
import requests
routes = {'https': 'http://proxy.example:8080'}
with requests.get(
'https://data.example/observations.csv',
proxies=routes,
stream=True,
timeout=(5, 30),
) as response:
response.raise_for_status()
response.encoding = 'utf-8'
lines = (
line + '\n'
for line in response.iter_lines(
chunk_size=65536, decode_unicode=True)
)
for record in csv.reader(lines, delimiter=';'):
if record and record[0] == 'wanted':
print(record)
break
اختر ترميز الملف الفعلي ولهجته. ولتنزيل CSV عام عبر مسار وكيل عام مسموح، تقدّم قائمة وكلاء HTTP مرشحين لعنوان routes. وتُطبِّع هذه النسخة نهايات الأسطر الفعلية إلى LF: يزيلها iter_lines، ويعيد المولِّد إضافة سطر جديد لمحلل CSV. ويُهمّ ذلك عندما يستمر حقل بين علامات اقتباس إلى سطر فعلي آخر.
ولسير العمل التي تتطلب حفظًا دقيقًا بالبايت لأحرف CRLF المضمّنة، استخدم ترتيب غلاف نصي متدفق يحفظ نهايات الأسطر تلك. والتطبيع المتعمد في المثال مناسب للمعالجة الموجهة بالسجلات حيث يكون LF هو التمثيل المقصود.
استجابة واحدة، قراءات كثيرة
يستهلك المكرِّر قطعًا من استجابة HTTP واحدة، ولا يُصدر طلبًا جديدًا لكل سطر. وطلبات HTTP Range آلية مختلفة، ولا تحدد حدود سجلات CSV بطبيعتها.
إن استدعاء response.text أو جمع كل الصفوف في قائمة سيعيد المحتوى الكامل إلى الذاكرة. ولا يزال البث بحاجة إلى مساحة لمخازن النقل وللسجل الحالي، الذي قد يحتوي هو نفسه على حقل كبير.
يغلق سياق الاستجابة الجسم عند خروج الحلقة، بما في ذلك عند تحقق تطابق مبكر. وتحدّ مهلة القراءة من انتظار البيانات الواردة، لا من العمر الكلي لنقل ملف كبير.