2013-06-13 5 views
8

更新:この記事の一番下にあるデバッグ情報がいくつかあります。インポートされたモジュールは、関数を実行するとNoneになります。

私は、とりわけdjango Userオブジェクトをインポートするモジュールを持っています。

インポートが正常に動作し、コードが読み込まれます。ただし、Userオブジェクトを使用するモジュールで関数を呼び出すと、UserがNoneTypeであるというエラーが発生します。

他にも多くのインポートがあり、モジュールレベルのグローバル変数もあります。これは、関数が呼び出されるまでにはNoneです。

これは私たちのステージング環境(Ubuntu 12.04)でのみ問題です。それはローカルでうまく動作します。おそらく、開発作業のために特別なPythonパッケージを使用してステージングするのに最もよく似ています。また、生産上も問題ありません。

これまでに誰もがこの問題を抱えていましたが、何が原因なのでしょうか?ここで

はコードです:

import urllib 
import time 
import urlparse 

# Django imports 
from django.db.models.signals import post_delete 
from django.db import models 
from django.contrib.auth.models import User 

from backends.cache.dualcache import cache 

# Piston imports 
from managers import TokenManager, ConsumerManager 
from signals import consumer_post_delete 

KEY_SIZE = 18 
SECRET_SIZE = 32 
VERIFIER_SIZE = 10 

CONSUMER_STATES = (
    ('pending', 'Pending'), 
    ('accepted', 'Accepted'), 
    ('canceled', 'Canceled'), 
    ('rejected', 'Rejected') 
) 


def generate_random(length=SECRET_SIZE): 
    return User.objects.make_random_password(length=length) 


class Consumer(models.Model): 
    name = models.CharField(max_length=255) 
    description = models.TextField() 

    key = models.CharField(max_length=KEY_SIZE) 
    secret = models.CharField(max_length=SECRET_SIZE) 

    status = models.CharField(max_length=16, choices=CONSUMER_STATES, default='pending') 

    objects = ConsumerManager() 

    def __unicode__(self): 
     return u"Consumer %s with key %s" % (self.name, self.key) 

    def generate_random_codes(self): 
     key = User.objects.make_random_password(length=KEY_SIZE) 
     secret = generate_random(SECRET_SIZE) 

     while Consumer.objects.filter(key__exact=key, secret__exact=secret).count(): 
      secret = generate_random(SECRET_SIZE) 

     self.key = key 
     self.secret = secret 
     self.save() 

、ここでは、周りの仕事だ、あなたが関数内で再び必要なものをインポートするには基本的に意味している:

import urllib 
import time 
import urlparse 

# Django imports 
from django.db.models.signals import post_delete 
from django.db import models 
from django.contrib.auth.models import User 

from backends.cache.dualcache import cache 

# Piston imports 
from managers import TokenManager, ConsumerManager 
from signals import consumer_post_delete 

KEY_SIZE = 18 
SECRET_SIZE = 32 
VERIFIER_SIZE = 10 

CONSUMER_STATES = (
    ('pending', 'Pending'), 
    ('accepted', 'Accepted'), 
    ('canceled', 'Canceled'), 
    ('rejected', 'Rejected') 
) 


def generate_random(length=SECRET_SIZE): 
    return User.objects.make_random_password(length=length) 


class Consumer(models.Model): 
    name = models.CharField(max_length=255) 
    description = models.TextField() 

    key = models.CharField(max_length=KEY_SIZE) 
    secret = models.CharField(max_length=SECRET_SIZE) 

    status = models.CharField(max_length=16, choices=CONSUMER_STATES, default='pending') 

    objects = ConsumerManager() 

    def __unicode__(self): 
     return u"Consumer %s with key %s" % (self.name, self.key) 

    def generate_random_codes(self): 
     from piston.models import KEY_SIZE, SECRET_SIZE, Consumer 
     from django.contrib.auth.models import User 
     from piston.models import generate_random 

     key = User.objects.make_random_password(length=KEY_SIZE) 
     secret = generate_random(SECRET_SIZE) 

     while Consumer.objects.filter(key__exact=key, secret__exact=secret).count(): 
      secret = generate_random(SECRET_SIZE) 

     self.key = key 
     self.secret = secret 
     self.save() 

ここでスタックトレースです。このエラーは、generate_random_codes関数の

key = User.objects.make_random_password(length=KEY_SIZE) 

の行によって発生します。

Traceback: 
File "/sites/tellybug/shared/webserver/local/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response 
    111.       response = callback(request, *callback_args, **callback_kwargs) 
File "/sites/tellybug/shared/webserver/local/lib/python2.7/site-packages/django/contrib/admin/options.py" in wrapper 
    366.     return self.admin_site.admin_view(view)(*args, **kwargs) 
File "/sites/tellybug/shared/webserver/local/lib/python2.7/site-packages/django/utils/decorators.py" in _wrapped_view 
    91.      response = view_func(request, *args, **kwargs) 
File "/sites/tellybug/shared/webserver/local/lib/python2.7/site-packages/django/views/decorators/cache.py" in _wrapped_view_func 
    89.   response = view_func(request, *args, **kwargs) 
File "/sites/tellybug/shared/webserver/local/lib/python2.7/site-packages/django/contrib/admin/sites.py" in inner 
    196.    return view(request, *args, **kwargs) 
File "/sites/tellybug/shared/webserver/local/lib/python2.7/site-packages/django/utils/decorators.py" in _wrapper 
    25.    return bound_func(*args, **kwargs) 
File "/sites/tellybug/shared/webserver/local/lib/python2.7/site-packages/django/utils/decorators.py" in _wrapped_view 
    91.      response = view_func(request, *args, **kwargs) 
File "/sites/tellybug/shared/webserver/local/lib/python2.7/site-packages/django/utils/decorators.py" in bound_func 
    21.     return func(self, *args2, **kwargs2) 
File "/sites/tellybug/shared/webserver/local/lib/python2.7/site-packages/django/db/transaction.py" in inner 
    224.     return func(*args, **kwargs) 
File "/sites/tellybug/shared/webserver/local/lib/python2.7/site-packages/django/contrib/admin/options.py" in add_view 
    970.    form = ModelForm(initial=initial) 
File "/sites/tellybug/shared/webserver/local/lib/python2.7/site-packages/django/forms/models.py" in __init__ 
    234.    self.instance = opts.model() 
File "/sites/tellybug/shared/webserver/local/lib/python2.7/site-packages/django/db/models/base.py" in __init__ 
    349.     val = field.get_default() 
File "/sites/tellybug/shared/webserver/local/lib/python2.7/site-packages/django/db/models/fields/related.py" in get_default 
    983.   field_default = super(ForeignKey, self).get_default() 
File "/sites/tellybug/shared/webserver/local/lib/python2.7/site-packages/django/db/models/fields/__init__.py" in get_default 
    379.     return self.default() 
File "/sites/tellybug/releases/b92109dd526607b2af92ad6b7f494f3f06e31bb2/webserver/tellybug/tbapp/models/tellybugapp.py" in generate_new_consumer 
    11.  consumer.generate_random_codes() 
File "/sites/tellybug/releases/b92109dd526607b2af92ad6b7f494f3f06e31bb2/webserver/tellybug/piston/models.py" in generate_random_codes 
    57. key = User.objects.make_random_password(length=KEY_SIZE) 

Exception Type: AttributeError at /admin/tbapp/tellybugapp/add/ 
Exception Value: 'NoneType' object has no attribute 'objects' 

更新:それはちょうど、ユーザーオブジェクトを削除するものではないのです - 何かが機能してコンテキスト全体を台無しています。これらのprint文で

def generate_random_codes(self): 
    """ 
    Used to generate random key/secret pairings. Use this after you've 
    added the other data in place of save(). 

    c = Consumer() 
    c.name = "My consumer" 
    c.description = "An app that makes ponies from the API." 
    c.user = some_user_object 
    c.generate_random_codes() 
    """ 
    import sys 
    print "Globals", globals() 
    print "Name ", __name__ 
    print "Package ", __package__ 
    print "Sys modules", sys.modules['piston.models'].__dict__ 
    key = User.objects.make_random_password(length=KEY_SIZE) 

、出力は次のようになります。私はかなり不可能であった、との間sys.modulesバージョンと考え__package____name__の両方が未定義であることを

Globals {'ColumnFamilyMap': None, 'datetime': None, 'KEY_SIZE': None, 'TokenManager': None, 'ConsistencyLevel': None, 'Nonce': None, 'uuid': None, 'cache': None, 'urllib': None, '__package__': None, 'models': None, 'User': None, .... } 
Name None 
Package None 
Sys modules {'ColumnFamilyMap': <class 'pycassa.columnfamilymap.ColumnFamilyMap'>, 'datetime': <type 'datetime.datetime'>, 'KEY_SIZE': 18, 'NonceType': <class 'piston.models.NonceType'>, 'OAuthToken': <class 'piston.models.OAuthToken'>, 'TokenManager': <class 'piston.managers.TokenManager'>, 'ConsistencyLevel': <class 'pycassa.cassandra.ttypes.ConsistencyLevel'>, 'Nonce': <class 'piston.models.Nonce'>, 'uuid': <module 'uuid' from '/usr/lib/python2.7/uuid.pyc'>, ...} 

注意、モジュールが正しい__dict__を持っていれば、globals()の戻り値はナンセンスです。

+1

例外をスローするコードと完全なトレースバックを表示してください。 –

+0

エラーは、どこから来たモデルから来ていないのですか?トレースバックも表示してください。 –

+0

ありがとうございました、エラーを投げているスタックトレースと行を追加しました。 –

答えて

7

これは、インポートされたモジュール内の関数で、そのモジュールがガベージコレクトされた後もまだ実行されています。

コードでは問題を再現するには不十分なので、ここではその動作を示す簡単な例を示します。以下を含むファイルを作成し、 Pythonコマンドラインまたは別のファイルからインポートします。トップレベルで を実行するだけでは機能しません。それを実行

import sys 
import threading 

x = "foo" 

def run(): 
    while True: 
     print "%s %s\n" % (sys, x) 

threading.Thread(target = run).start() 
sys.stdin.readline() 

は:Pythonのシャットダウン時

$ python 
>>> import evil_threading 
<module 'sys' (built-in)> foo 

<module 'sys' (built-in)> foo 
... press Ctrl-C 
None None 

None None 
... press Ctrl-\ to kill the Python interpreter 

、モジュールはNoneに設定されています。 This is an obscure Python behaviour that was removed in 3.4。 この例では、メインスレッドを終了するとシャットダウンしますが、もう1つのスレッドはまだ実行されているため、モジュールはNoneと表示されます。

より簡単な例from hereは、モジュール参照をsys.modulesから直接削除することで同じことを行います。

import sys 
print sys 
del sys.modules['__main__'] 
print sys 
関連する問題