سؤال

أقوم بإنشاء ملف يسمى foo_module.py يحتوي على الكود التالي:

import shelve, whichdb, os

from foo_package.g import g

g.shelf = shelve.open("foo_path")
g.shelf.close() 

print whichdb.whichdb("foo_path")  # => dbhash
os.remove("foo_path")

بجانب هذا الملف أقوم بإنشاء دليل يسمى foo_package من يحتوي على فارغة __init__.py ملف وملف يسمى g.py هذا يحتوي فقط على:

class g:
    pass

الآن عندما أركض foo_module.py أحصل على رسالة خطأ غريبة:

Exception TypeError: "'NoneType' object is not callable" in ignored

ولكن بعد ذلك ، إذا قمت بإعادة تسمية الدليل من foo_package ل foo, وتغيير خط الاستيراد في foo_module.py, ، لا أحصل على أي خطأ. WTF يحدث هنا؟

تشغيل Python 2.6.4 على WinXP.

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

المحلول

أعتقد أنك ضربت خطأ بسيط في رمز 2.6.4 المتعلق بالتنظيف في نهاية البرنامج. اذا ركضت python -v يمكنك أن ترى بالضبط في أي نقطة من التنظيف يأتي الخطأ:

# cleanup[1] foo_package.g
Exception TypeError: "'NoneType' object is not callable" in  ignored

بيثون يحدد إشارات إلى None أثناء التنظيف في نهاية البرنامج ، ويبدو أنه يربك في حالة g.shelf. كحل يمكن أن تضعه g.shelf = None بعد close. أود أن أوصي أيضًا بفتح خطأ في تعقب الأخطاء في بيثون!

نصائح أخرى

بعد أيام من تساقط الشعر ، حققت أخيرًا نجاحًا باستخدام وظيفة ATEXIT:

  import atexit
  ...
  cache = shelve.open(path)
  atexit.register(cache.close)

من الأنسب للتسجيل مباشرة بعد الافتتاح. هذا يعمل مع عدة أرفف متزامنة.

(Python 2.6.5 على Lucid)

هذا بالفعل خطأ في بيثون ، وقد نشرت رقعة على مشكلة المتتبع التي فتحتها (شكرًا على القيام بذلك).

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

يمكنك تجنب الرسالة في الكود الخاص بك عن طريق إضافة "del g.shelf" بعد g.shelf.close. طالما أن G.Shelf هو الإشارة الوحيدة إلى الرف ، فإن هذا سيؤدي إلى استدعاء Cpython The Shelve ديل الطريقة على الفور ، قبل مرحلة تنظيف المترجم ، وبالتالي تجنب رسالة الخطأ.

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

بالنسبة لي بسيطة shelve.close() على واحد غير مُعد هذا الوظيفة.

إرجاع Leadve.Open ('SomeFile') كائن "قاموس مستمر للقراءة والكتابة" التي استخدمتها خلال وقت تشغيل التطبيق. عندما أنهيت التطبيق ، تلقيت استثناء "typeerror" كما هو مذكور. لقد قمت بإلغاء استدعاء "Close ()" في تسلسل الإنهاء الخاص بي ويبدو أنه يحل المشكلة.

على سبيل المثال chelveobj = legve.open ('filename') ... legveobj.close ()

علق Overwyere على 17 يوليو 2018

يبدو أن هذا يمكن تثبيته.

باختصار Open /usr/lib/python3.5/weakref.py وتغيير السطر 109 إلى:

 def remove(wr, selfref=ref(self), _atomic_removal=_remove_dead_weakref):

والخط 117 إلى:

_atomic_removal(d, wr.key)

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

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