سؤال

كتبت نصًا بيثون لمعالجة بعض البيانات من ملفات CSV. يستغرق البرنامج النصي ما بين 3 إلى 30 دقيقة لإكماله ، اعتمادًا على حجم CSV.

الآن أريد وضع واجهة ويب لهذا ، حتى أتمكن من تحميل ملفات بيانات CSV من أي مكان. لقد كتبت صفحة تحميل HTTP الأساسية واستخدمت وحدة CGI Python - ولكن البرنامج النصي في وقت من الأوقات بعد مرور بعض الوقت.

يقوم البرنامج النصي بإخراج رؤوس HTTP في البداية ، ويخرج أجزاء من البيانات بعد التكرار على كل سطر من CSV. على سبيل المثال ، سيؤدي هذا البيان المطبوع إلى تشغيل كل 30 ثانية أو نحو ذلك.

# at the very top, with the 'import's
print "Content-type: text/html\n\n Processing ... <br />"

# the really long loop.
for currentRecord in csvRecords:
    count = count + 1
    print "On line " + str(count) + " <br />"

افترضت أن المتصفح سيتلقى الرؤوس ، وانتظر لأنه يستمر في تلقي أجزاء صغيرة من البيانات. ولكن ما يبدو في الواقع هو أنه لا يتلقى أي بيانات على الإطلاق ، و Error 504 مرات في الخارج عند إعطاء CSV مع الكثير من الخطوط.

ربما هناك بعض التخزين المؤقت يحدث في مكان ما؟ من السجلات ،

[Wed Jan 20 16:59:09 2010] [error] [client ::1] Script timed out before returning headers: datacruncher.py, referer: http://localhost/index.htm
[Wed Jan 20 17:04:09 2010] [warn] [client ::1] Timeout waiting for output from CGI script /Library/WebServer/CGI-Executables/datacruncher.py, referer: http://localhost/index.htm

ما هي أفضل طريقة لحل هذا ، أو ، أليس من المناسب تشغيل مثل هذه البرامج النصية في المتصفح؟

تعديل:هذا نص لاستخدامي الخاص - عادةً ما أعتزم استخدامه على جهاز الكمبيوتر الخاص بي ، لكنني اعتقدت أن الواجهة المستندة إلى الويب يمكن أن تكون مفيدة أثناء السفر ، أو على سبيل المثال من الهاتف. أيضًا ، لا يوجد شيء يتم تنزيله حقًا - على الأرجح أن البرنامج النصي سوف يرسل تقريرًا عن النهاية في النهاية.

هل كانت مفيدة؟

المحلول

أود أن أفصل العمل مثل هذا:

  1. عنوان URL تطبيق الويب الذي يقبل ملف CSV المنشور. يضع تطبيق الويب محتوى CSV في قائمة انتظار خارج الخط ، على سبيل المثال جدول قاعدة البيانات. يجب أن تكون استجابة تطبيق الويب معرّفًا فريدًا للعنصر القائم على قائمة الانتظار (استخدم عمود معرف تم تثبيته تلقائيًا ، على سبيل المثال). يجب على العميل تخزين هذا المعرف للجزء 3.

  2. تطبيق خدمة مستقلة يقوم باستطلاع قائمة الانتظار للعمل ، ويقوم بالمعالجة. عند الانتهاء من المعالجة ، قم بتخزين النتائج في جدول قاعدة بيانات أخرى ، باستخدام المعرف الفريد كمفتاح.

  3. عنوان URL لتطبيق الويب الذي يمكن أن يحصل على نتائج معالجة ، http://server/getresults/uniqueid/. إذا تم الانتهاء من المعالجة (أي تم العثور على المعرف الفريد في جدول قاعدة بيانات النتائج) ، ثم أعد النتائج. إذا لم تنته ، يجب أن تكون الاستجابة رمزًا يشير إلى ذلك. على سبيل المثال ، رأس HTTP مخصص ، استجابة حالة HTTP ، جسم الاستجابة "معلق" أو ما شابه.

نصائح أخرى

لقد حصلت على هذا الموقف من قبل واستخدمت cronjobs. سوف يكتب البرنامج النصي HTTP في قائمة انتظار وظيفة ليتم تنفيذها (DB أو ملف في دليل) وسيقوم Cronjob بقراءتها وتنفيذ هذه الوظيفة.

ربما ستحتاج إلى القيام stdout.flush(), ، نظرًا لأن البرنامج النصي لا يكتب أي شيء حتى الآن إلى خادم الويب حتى تقوم بكتابة بيانات مخزن مؤقت للصفحة - وهو ما لا يحدث قبل المهلة.

ولكن الطريقة الصحيحة لحل ذلك ، كما اقترح آخرون ، القيام بالمعالجة في مؤشر ترابط/عملية منفصلة ، وإظهار الصفحة التي تم تحريرها تلقائيًا تُظهر الحالة ، مع شريط تقدم أو بعض المرئيات الرائعة الأخرى للحفاظ عليها من الشعور بالملل.

انظر راندال شوارتز مشاهدة عمليات طويلة من خلال CGI. تستخدم المقالة Perl ، لكن التقنية لا تعتمد على اللغة.

سؤال مشابه جدا هنا. أقترح التفويف على العملية الطويلة وإعادة شريط التقدم القائم على أياكس إلى المستخدم. وبهذه الطريقة ، يكون لدى المستخدم رفاهية واجهة الويب ولديك رفاهية أي مهلة.

IMHO أفضل طريقة هي تشغيل برنامج نصي مستقل ينشر التحديثات في مكان ما (ملف مسطح ، قاعدة بيانات ، إلخ ...). لا أعرف كيف أتخلى عن عملية مستقلة من Python حتى لا أستطيع إعطاء أي أمثلة رمز.

لإظهار التقدم على موقع ويب ، قم بتنفيذ طلب AJAX على صفحة تقرأ تحديثات الحالة هذه ، وعلى سبيل المثال ، يعرض شريط تقدم لطيف.

أضف شيئًا مثل setTimeout ("RefreshProgressBar [...]) أو meta-refresh لـ Auto-Refresh.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top