LINUX.ORG.RU

python, NameError: global name NAME is not defined

 


0

1

Есть небольшое недопонимание

Есть код

$ cat test.py
#!/usr/bin/python


class A:
    def test(self):
        print urllib


if __name__ == '__main__':
    import urllib
    a=A()
    a.test()

при запуске файла все работает
$ python test.py
<module 'urllib' from '/usr/lib/python2.7/urllib.pyc'>
Если импортировать класс в консоли и импортировать модуль - ловим исключение
$ python
Python 2.7.12 (default, Dec  4 2017, 14:50:18) 
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import urllib
>>> from test import A
>>> a=A()
>>> a.test()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "test.py", line 6, in test
    print urllib
NameError: global name 'urllib' is not defined
Почему так происходит и возможно ли провести манипуляции в консоли для починки, не меняя файл(не вынося импорт) из под условия


Ответ на: комментарий от entefeed

В третьем тоже самое, так что если хочешь представь что это третий.

Вообще я просто не хотел делать повторный импорт одно и того же модуля, когда класс импортирую из файла. Но думаю в это ничего плохого, и можно вынести импорт из под условия.

swelf ()
Ответ на: комментарий от swelf

как это в третьем тоже самое, если там прямо есть специальные ключевые слова для нелокальных переменных nonlocal и global?

Upd: позапускал пример — действительно, в третьем такая же фигня...

Sahas ★★★★★ ()
Последнее исправление: Sahas (всего исправлений: 2)
Ответ на: комментарий от Sahas

global и во втором есть, я правда не пользовался особо. Мне все 100500 импортированных модулей как global объявлять?

Я скорей хотел узнать, почему, если я импортирую модуль в консоли, а не в скрипте, то мой класс его не видит. А если просто запускаю файл, который выполняет вроде бы тот же код, то все работает и оба питона тут ведут себя одинаково

swelf ()
Ответ на: комментарий от swelf

Я скорей хотел узнать, почему, если я импортирую модуль в консоли, а не в скрипте, то мой класс его не видит.

Потому, что ты импортировал его в консоли, а не в самом модуле?

shkolnick-kun ★★★ ()
Ответ на: комментарий от swelf

Вот где я нашёл разницу:

cat test.py
class A:
    def test(self):
        print(urllib)


if __name__ == '__main__':
    import urllib
    a=A()
    print(A())

python -i test.py
<__main__.A object at 0x7f65a4834b00>
>>> from test import A
>>> A()
<test.A object at 0x7f65a483f160>
Sahas ★★★★★ ()
Последнее исправление: Sahas (всего исправлений: 1)
Ответ на: комментарий от shkolnick-kun

-Хочешь совет? Но он тебе не понравится

-Давай

-Ты рано женился

-Но это не совет

-А я предупреждал

Потому, что ты импортировал его в консоли, а не в самом модуле?

И ежу понятно, я хотел узнать, почему такое поведение. Хотя казалось бы должно все работать.

Но почитал кое чего про пространства имен и все такое. И вроде разобрался.

import test
test.urllib = urllib
a.test()

пожалуй буду такого избегать и просто норм импортировать модули

swelf ()
Ответ на: комментарий от shkolnick-kun

да неужели?

class A:
    def test(self):
        print(var)

var = ["i'm here"]
>>> from test import *
>>> var
["i'm here"]
>>> var[0] = 'but why?'
>>> A().test()
['but why?']

и почему питон 2 жалуется на то, что имя не определено в глобальном ПИ, хотя оно там определено?

anonymous ()

Почему так происходит

if __name__ == '__main__':
    import urllib

ты импортируешь urllib только если __name__ == '__main__', т.е. если модуль запущен напрямую. поэтому при импорте через import в пространстве имен модуля никакого urllib нет.

возможно ли провести манипуляции в консоли для починки

выше написали

не меняя файл(не вынося импорт) из под условия

не знаю, что это за искусственное ограничение, и не буду спрашивать

MyTrooName ★★★★★ ()
Ответ на: комментарий от anonymous

Потому, что имя urllib не определено в теле метода test, соответственно, интерпретатор обрабатывает его так, как будто перед print urllib было global urllib, соответственно global - ключевое слово, а не обозначение глобального пространства имен.

Если что в 3.6 выводится вот так:

NameError: name 'urllib' is not defined

shkolnick-kun ★★★ ()
Последнее исправление: shkolnick-kun (всего исправлений: 1)
Ответ на: комментарий от shkolnick-kun

ладно, хорошо. но ты не сказал, что, при импорте *, объекты из модуля биндятся к именам текущего пространства, а это важно. поэтому только четвёрка.

anonymous ()

Месье, обратите внимание на это условие (которое, как ни странно, написали вы сами):

if __name__ == '__main__':

Это условие проверяет содержимое глобальной переменной __name__. Эта переменная содержит строку "__main__", когда файл исполняется как скрипт, т.е. $ python script.py
Когда же файл используется как модуль, т.е. в другом файле выполняется import module, тогда переменная __name__ довольно логично содержит строку с именем этого файла (естественно, без расширения ".py").

Таким образом условная ветка

if __name__ == '__main__':
    import urllib
    a=A()
    a.test()
выполняется только, если файл используется как скрипт. В вашем случае вы его используете как модуль, поэтому никакого модуля «urllib» не импортируется, а следовательно, и найти его в ни в локальном, ни в глобальном пространствах имен невозможно.

P.S. RTFM.

Virtuos86 ★★★★★ ()
Ответ на: комментарий от swelf

повторный импорт одно и того же модуля

Не бывает никаких повторных импортов, импорт модуля происходит один единственный раз, повторно ты лишь создаёшь ссылку на него. Можешь убедиться потыкав `sys.modules`.

Ну а остальное тебе уже объяснили.

WitcherGeralt ★★ ()
Последнее исправление: WitcherGeralt (всего исправлений: 1)
Ответ на: комментарий от garik_keghen

дело на самом деле в джанге, не рекомендуется делать django.setup() несколько раз, хз что там происходит. Я почему то думал что cache из django.core.cache можно импортировать только после setup(), вот и запихал импорт в условие, но на самом деле можно.

swelf ()