python - كيفية تصحيح في Django ، الطريق الصحيح؟




debugging (18)

لذلك ، بدأت في تعلم Python في Python ولاحقًا Django . في المرات الأولى كان من الصعب النظر في tracebacks وفعلا معرفة ما فعلته خطأ وحيث كان خطأ في بناء الجملة. لقد مر بعض الوقت الآن وبطريقة ما ، أعتقد أني حصلت على روتين في تصحيح رمز دجانجو الخاص بي. بما أن هذا تم في وقت مبكر من تجربة الترميز الخاصة بي ، جلست وتساءلت إذا كان كيف كنت أفعل ذلك غير فعال ويمكن القيام به بشكل أسرع. عادةً ما أتمكن من العثور على الأخطاء وتصحيحها في شفرتي ، لكنني أتساءل عما إذا كان ينبغي عليّ القيام بذلك بشكل أسرع؟

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

لكن هل يمكن تحسين ذلك؟ هل هناك بعض الأدوات الجيدة أو طرق أفضل لتصحيح رمز Django الخاص بك؟


أثناء التطوير ، إضافة سريع

assert False, value

يمكن أن يساعد في تشخيص المشاكل في طرق العرض أو في أي مكان آخر ، دون الحاجة إلى استخدام مصحح الأخطاء.


أجد Visual Studio Code رائع لتصحيح أخطاء تطبيقات Django. تعمل معلمات launchyjon القياسية python على تشغيل python manage.py مع مصحح الأخطاء المرفقة ، بحيث يمكنك ضبط نقاط التوقف والدخول خلال الشفرة كما تشاء.


أستخدم PyCharm وأدوات تصحيح الأخطاء المختلفة. أيضا لديها مجموعة من المواد لطيفة حول إعداد سهل لتلك الأشياء للمبتدئين. يمكنك البدء من هنا. ويحكي عن PDB و GUI التصحيح بشكل عام مع مشاريع Django. آمل أن يستفيد شخص منهم.


أسهل طريقة لتصحيح python - خاصة للمبرمجين المستخدمة في Visual Studio - يستخدم PTVS (أدوات Python لـ Visual Studio). الخطوات بسيطة:

  1. قم بتنزيله وتثبيته من http://pytools.codeplex.com/
  2. تعيين breakpoints واضغط F5.
  3. يتم الوصول إلى نقطة الإيقاف الخاصة بك ، يمكنك عرض / تغيير المتغيرات بسهولة مثل تصحيح برامج C # / C ++.
  4. هذا كل شئ :)

إذا كنت تريد تصحيح أخطاء Django باستخدام PTVS ، فستحتاج إلى إجراء ما يلي:

  1. في إعدادات المشروع - علامة التبويب عام ، اضبط "ملف بدء التشغيل" على "manage.py" ، نقطة الدخول لبرنامج Django.
  2. في إعدادات Project - Debug tab ، اضبط "Script Arguments" على "runningerver --noreload". النقطة الأساسية هي "--noreload" هنا. إذا لم تقم بتعيينه ، فلن يتم ضرب نقاط التوقف الخاصة بك.
  3. استمتع بها.

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



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

لا بد لي من القول ، أن PyCharm يأخذ الكثير من الذاكرة. لكن مرة أخرى ، لا شيء جيد في الحياة. لقد أتيت للتو بأحدث إصدار 3. كما أنها تلعب بشكل جيد للغاية مع Django و Flask و Google AppEngine. لذا ، على العموم ، أود أن أقول إنها أداة رائعة ومفيدة لأي مطور.

إذا كنت لا تستخدمها حتى الآن ، فإنني أوصيك بالحصول على النسخة التجريبية لمدة 30 يومًا لإلقاء نظرة على قوة PyCharm. أنا متأكد من أن هناك أدوات أخرى متاحة أيضًا ، مثل Aptana. ولكن أعتقد أنني فقط أحب الطريقة التي تبدو بها PyCharm. أشعر براحة كبيرة في تصحيح تطبيقاتي هناك.


أنا حقاً أحب المصحح التفاعلي لـ Werkzeug . تشبه صفحة debug في Django ، إلا أنه يمكنك الحصول على غلاف تفاعلي على كل مستوى من التتبع. إذا كنت تستخدم django-extensions ، فستحصل على أمر إدارة runserver_plus يبدأ خادم التطوير ويمنحك مصحح الأخطاء الخاص بـ Werkzeug على الاستثناءات.

بالطبع ، يجب عليك فقط تشغيل هذا محليًا ، لأنه يمنح أي شخص لديه متصفح الحق في تنفيذ شفرة python عشوائية في سياق الخادم.


استخدم pdb أو ipdb . Diffrence بين هذين هما ipdb يدعم السيارات كاملة.

ل pdb

import pdb
pdb.set_trace()

ل ipdb

import ipdb
ipdb.set_trace()

لتنفيذ مفتاح السطر الجديد ، اضغط على مفتاح c للمتابعة. تحقق من المزيد من الخيارات باستخدام help(pdb)


اقتراح إضافي.

يمكنك الاستفادة من nosetests و pdb معا ، بدلا عن طريق حقن pdb.set_trace() في وجهات النظر الخاصة بك يدويا. وتتمثل الميزة في أنه يمكنك مراقبة حالات الخطأ عند بدء التشغيل لأول مرة ، ومن المحتمل أن يكون ذلك في رمز جهة خارجية.

إليك خطأ بالنسبة لي اليوم.

TypeError at /db/hcm91dmo/catalog/records/

render_option() argument after * must be a sequence, not int

....


Error during template rendering

In template /opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/crispy_forms/templates/bootstrap3/field.html, error at line 28
render_option() argument after * must be a sequence, not int
18  
19          {% if field|is_checkboxselectmultiple %}
20              {% include 'bootstrap3/layout/checkboxselectmultiple.html' %}
21          {% endif %}
22  
23          {% if field|is_radioselect %}
24              {% include 'bootstrap3/layout/radioselect.html' %}
25          {% endif %}
26  
27          {% if not field|is_checkboxselectmultiple and not field|is_radioselect %}
28  

      {% if field|is_checkbox and form_show_labels %}

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

أجل، أستطيع. باستخدام خيار --pdb على nosetests:

tests$ nosetests test_urls_catalog.py --pdb

بمجرد أن تصل إلى أي استثناء (بما في ذلك تلك التي يتم التعامل معها بأمان) ، يتوقف pdb حيث يحدث ويمكنني أن ننظر حولها.

  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/forms/forms.py", line 537, in __str__
    return self.as_widget()
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/forms/forms.py", line 593, in as_widget
    return force_text(widget.render(name, self.value(), attrs=attrs))
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/forms/widgets.py", line 513, in render
    options = self.render_options(choices, [value])
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/forms/widgets.py", line 543, in render_options
    output.append(self.render_option(selected_choices, *option))
TypeError: render_option() argument after * must be a sequence, not int
INFO lib.capture_middleware log write_to_index(http://localhost:8082/db/hcm91dmo/catalog/records.html)
INFO lib.capture_middleware log write_to_index:end
> /opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/forms/widgets.py(543)render_options()
-> output.append(self.render_option(selected_choices, *option))
(Pdb) import pprint
(Pdb) pprint.PrettyPrinter(indent=4).pprint(self)
<django.forms.widgets.Select object at 0x115fe7d10>
(Pdb) pprint.PrettyPrinter(indent=4).pprint(vars(self))
{   'attrs': {   'class': 'select form-control'},
    'choices': [[('_', 'any type'), (7, (7, 'type 7', 'RECTYPE_TABLE'))]],
    'is_required': False}
(Pdb)         

الآن ، من الواضح أن حجة اختياراتي لمنشئ الحقل المتموج كانت كما لو كانت قائمة ضمن قائمة ، بدلاً من قائمة / مجموعة tuples.

 'choices': [[('_', 'any type'), (7, (7, 'type 7', 'RECTYPE_TABLE'))]]

الشيء الجيد هو أن هذا pdb يحدث داخل رمز كريسبي ، وليس لي وأنا لم أكن في حاجة لإدخاله يدويا.


تم ذكر كل شيء تقريبًا حتى الآن ، لذا سأضيف أنه بدلاً من pdb.set_trace() يمكن استخدام ipdb.set_trace () الذي يستخدم iPython وبالتالي فهو أكثر قوة (الإكمال التلقائي وأشياء أخرى جيدة). هذا يتطلب حزمة ipdb ، لذلك تحتاج فقط إلى pip install ipdb


في بعض الأحيان عندما أتمكن من استكشاف طريقة معينة واستدعاء pdb أمر مرهق للغاية ، أود أن أضيف:

import IPython; IPython.embed()

يبدأ IPython.embed() shell IPython التي لديها الوصول إلى المتغيرات المحلية من النقطة حيث يمكنك الاتصال به.


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

للقيام بذلك ، أوصي باستخدام WingIde. تماما مثل غيرها من IDEs لطيفة وسهلة الاستخدام ، تخطيط لطيف وأيضا من السهل أن تحدد breakpoints / تعديل المكدس الخ. مثالي لتصور ما تقوم به الكود الخاص بك أثناء الخطو خلاله. أنا من أشد المعجبين به.

أنا أيضا استخدام PyCharm - لديها تحليل رمز ثابت ممتازة ويمكن أن تساعد في بعض الأحيان اكتشاف المشاكل قبل أن تدرك أنهم هناك.

كما ذكر بالفعل django-debug-toolbar ضروري - https://github.com/django-debug-toolbar/django-debug-toolbar

وعلى الرغم من عدم صراحة أداة تصحيح أو تحليل - واحدة من المفضلة هي SQL Middleware المتاحة من Django Snippets على https://djangosnippets.org/snippets/290/

سيقوم هذا بعرض استعلامات SQL التي أنشأها العرض الخاص بك. سيعطيك ذلك إحساسًا جيدًا لما تقوم به ORM وإذا كانت استعلاماتك فعالة أو تحتاج إلى إعادة صياغة التعليمات البرمجية (أو إضافة التخزين المؤقت).

أجد أنه لا يقدر بثمن لابقاء العين على أداء الاستعلام أثناء تطوير وتصحيح طلبي.

نصيحة واحدة فقط - لقد قمت بتعديله قليلاً لاستخدامي الخاص لإظهار الملخص فقط وليس عبارة SQL .... لذلك أنا استخدمه دائمًا أثناء التطوير والاختبار. أضفت أيضًا أنه إذا كان len (connection.queries) أكبر من عتبة محددة مسبقًا ، فإنه يعرض تحذيرًا إضافيًا.

ثم إذا كنت أرى شيئا سيئا (من أداء أو عدد من منظور الاستعلامات) يحدث أنا أعود مرة أخرى على العرض الكامل للعبارات SQL لنرى بالضبط ما يجري. سهل جداً عندما تعمل على مشروع كبير في Django مع العديد من المطورين.


لقد دفعت django-pdb إلى django-pdb . إنه تطبيق بسيط يعني أنك لست بحاجة إلى تعديل شفرة المصدر في كل مرة تريد فيها اختراق pdb.

التثبيت هو فقط ...

  1. pip install django-pdb
  2. أضف 'django_pdb' إلى INSTALLED_APPS

يمكنك الآن التشغيل: manage.py runserver --pdb لاقتحام pdb في بداية كل مشاهدة ...

bash: manage.py runserver --pdb
Validating models...

0 errors found
Django version 1.3, using settings 'testproject.settings'
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

GET /
function "myview" in testapp/views.py:6
args: ()
kwargs: {}

> /Users/tom/github/django-pdb/testproject/testapp/views.py(7)myview()
-> a = 1
(Pdb)

وتشغيل: manage.py test --pdb لاقتحام pdb على فشل الإختبارات / أخطاء ...

bash: manage.py test testapp --pdb
Creating test database for alias 'default'...
E
======================================================================
>>> test_error (testapp.tests.SimpleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File ".../django-pdb/testproject/testapp/tests.py", line 16, in test_error
    one_plus_one = four
NameError: global name 'four' is not defined
======================================================================

> /Users/tom/github/django-pdb/testproject/testapp/tests.py(16)test_error()
-> one_plus_one = four
(Pdb)

يستضيف المشروع على GitHub ، المساهمات موضع ترحيب بالطبع.


معظم الخيارات المذكورة هي alredy. لطباعة سياق القالب ، قمت بإنشاء مكتبة بسيطة لذلك. راجع https://github.com/edoburu/django-debugtools

يمكنك استخدامه لطباعة سياق القالب بدون أي بناء {% load %} :

{% print var %}   prints variable
{% print %}       prints all

ويستخدم تنسيق pprint مخصص لعرض المتغيرات في علامة <pre> .


من وجهة نظري ، يمكننا تحليل مهام تصحيح الشفرات الشائعة إلى ثلاثة أنماط استخدام مميزة:

  1. وقد أثار شيء استثناء : django-extensions "Werkzeug المصحح للانقاذ. القدرة على تشغيل التعليمات البرمجية المخصصة في جميع مستويات التتبع هو القاتل. وإذا كنت عالقًا تمامًا ، يمكنك إنشاء Gist للمشاركة بنقرة واحدة فقط.
  2. يتم تقديم الصفحة ، ولكن النتيجة خاطئة : مرة أخرى ، الصخور Werkzeug. لجعل نقطة توقف في التعليمات البرمجية ، فقط اكتب assert False في المكان الذي تريد التوقف عنده.
  3. يعمل الرمز بشكل خاطئ ، لكن المظهر السريع لا يساعد. على الأرجح ، مشكلة حسابية. تنهد. ثم أنا عادة النار حتى مصحح وحدة التحكم pudb : import pudb; pudb.set_trace() import pudb; pudb.set_trace() . الميزة الرئيسية على [i] pdb هو أن PuDB (أثناء النظر كما كنت في الثمانينات) يجعل تعيين تعبيرات الساعة المخصصة نسيم. وتصحيح مجموعة من الحلقات المتداخلة يكون أبسط بكثير باستخدام واجهة المستخدم الرسومية.

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

هكذا يذهب.


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

import pdb; pdb.set_trace()

إذا حاولت تحميل هذه الصفحة في المستعرض الخاص بك ، فإن المتصفح سوف يتعطل والحصول على مطالبة لمواصلة تصحيح الأخطاء على كود التنفيذ الفعلي.

ومع ذلك هناك خيارات أخرى (أنا لا أوصي بها):

* return HttpResponse({variable to inspect})

* print {variable to inspect}

* raise Exception({variable to inspect})

ولكن يوصى بشدة باستخدام Python Debugger (pdb) لجميع أنواع شفرة Python. إذا كنت بالفعل في pdb ، فستحتاج أيضًا إلى إلقاء نظرة على IPDB الذي يستخدم ipython لتصحيح الأخطاء.

بعض التمديد أكثر فائدة ل pdb هي

pdb++ ، اقترحه Antash .

pudb ، اقترحه PatDuJour .

باستخدام مصحح Python في Django ، اقترح بواسطة Seafangs .


واحد من أفضل الخيارات لتصحيح رمز Django هو عبر wdb: https://github.com/Kozea/wdb

يعمل wdb مع python 2 (2.6، 2.7)، python 3 (3.2، 3.3، 3.4، 3.5) و pypy. والأفضل من ذلك ، أنه من الممكن تصحيح برنامج python 2 مع خادم wdb يعمل على python 3 والعكس بالعكس أو تصحيح برنامج يعمل على كمبيوتر مع خادم تصحيح يعمل على كمبيوتر آخر داخل صفحة ويب على كمبيوتر ثالث! والأفضل من ذلك أنه أصبح من الممكن الآن إيقاف عملية / مؤشر بايثون قيد التشغيل حاليًا باستخدام حقن الكود من واجهة الويب. (يتطلب ذلك استخدام gdb و ptrace) بمعنى آخر ، إنه نسخة محسنة للغاية من pdb مباشرة في متصفحك بميزات رائعة.

تثبيت الخادم وتشغيله ، وفي الشفرة الخاصة بك إضافة:

import wdb
wdb.set_trace()

وفقا للكاتب ، الاختلافات الرئيسية فيما يتعلق pdb هي:

بالنسبة لأولئك الذين لا يعرفون المشروع ، فإن wdb هو مصحح أخطاء python مثل pdb ، ولكن مع واجهة ويب ناعمة بالإضافة إلى الكثير من الميزات الإضافية ، مثل:

  • تسليط الضوء على بناء الجملة المصدر
  • نقاط التوقف البصرية
  • اكتمال التعليمة البرمجية التفاعلية باستخدام jedi
  • نقاط التوقف الثابتة
  • تفتيش الكائنات العميقة باستخدام الماوس دعم Multithroot / Multiprocessing
  • التصحيح عن بعد
  • مشاهدة التعبيرات
  • في إصدار التعليمات البرمجية المصحح
  • دمج خوادم الويب الشائعة لكسر الخطأ
  • في استثناء كسر أثناء التتبع (وليس بعد الوفاة) على عكس المصحح werkzeug على سبيل المثال
  • كسر في البرامج قيد التشغيل حاليا من خلال حقن الكود (على الأنظمة المدعومة)

يحتوي على واجهة مستخدم رائعة مستندة إلى مستعرض. فرحة للاستخدام! :)







debugging