Почему я получаю сообщение об ошибке: nameError: имя tk не определено, хотя я определил имя tk?

Я делаю редактор кода. Но когда я набираю в своем редакторе кода следующий код, он получает NameError.

import tkinter as tk

class App(tk.Tk):
    def __init__(self):
        super().__init__()
        self.label = tk.Label(self, text = "iets") # here, tk isn't recognized
        self.label.pack()
        
app = App()
app.mainloop()

Весь код входного текстового виджета tkinter выполняется оператором exec. Весь NameError:

Traceback (последний последний вызов): Файл "C:\Users\Gebruiker\PycharmProjects\mylanguage\execute.py", строка 24, in do exec (самостоятельный ввод) Файл "<string>", строка 9, в Файл "<строка>", строка 6, в __ init__ NameError: имя «tk» не определено

Почему я получаю эту ошибку? в коде, который я набрал, у меня есть import tkinter as tk!

Иерархия моего проекта следующая: У меня есть 8 файлов: main.py, execute.py, output.py и так далее.

  • Из main.py создается приложение tkinter.
  • Когда я нажимаю кнопку запуска, в execute.py код, как говорится, выполняется.
  • Затем вывод или ошибка отображаются в окне верхнего уровня из файла output.py.

выполнить.py:

...
    def do(self):
        sys.stdout.write = output
        try:
            set_last("")
            exec(self.input) #line 24
        except Exception:
            set_last("text.config(foreground='red')")
            error = traceback.format_exc()
            output(error)
...

когда я добавляю print(repr(self.input)) поверх do(), он выводит:

import tkinter as tk

class App(tk.Tk):
    def __init__(self):
        super().__init__()
        self.label = tk.Label(self, text = "iets")
        self.label.pack()
        
app = App()
app.mainloop()

Весь проект смотрите на github: https://github.com/keizertje/myl

заранее спасибо!

Сообщение об ошибке относится к строке 24, которой явно нет в этом коде. Покажи нам свой реальный код.

John Gordon 16.02.2023 19:41

когда я покажу вам все свои 8 файлов, мой вопрос станет не совсем ясным

Jasper Bart 16.02.2023 19:42

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

Jasper Bart 16.02.2023 19:43

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

John Gordon 16.02.2023 19:44

Если я нажму на ссылку на ваш репозиторий github, я получу ошибку 404 (это случайно не частный репозиторий?). Кроме того, имейте в виду, что идея Stackoverflow заключается в том, что вопросы автономны и не зависят от внешних ссылок, которые могут измениться или исчезнуть. В основном, если кто-то найдет вопрос в будущем, он сможет понять всю проблему (и, надеюсь, решение)

BorrajaX 16.02.2023 19:46

Большинство людей не хотят переходить по какой-либо внешней ссылке и копаться в горах кода, чтобы помочь вам решить вашу проблему. Ваша задача — дать нам небольшой (но полный) пример.

John Gordon 16.02.2023 19:48

@BorrajaX, извините, я опубликую свой репозиторий

Jasper Bart 16.02.2023 19:49

Есть ли шанс, что где-то в вашем проекте есть файл с именем tkinter или tk, который вызывает конфликт?

JRiggles 16.02.2023 19:53

я уверен, что у меня нет файла с именем tkinter

Jasper Bart 16.02.2023 19:54
exec будет запускать текст как Python. Этот текст (значение: self.input) где-то содержит tk?
BorrajaX 16.02.2023 19:55
self.input — это текст, который я набрал в своем редакторе кода, см. начало моего вопроса.
Jasper Bart 16.02.2023 19:56

Покажите нам точный вывод этого кода: print(repr(self.input)) вы можете добавить эту строку вверху do()

John Gordon 16.02.2023 20:00

О, я понимаю, что вы имеете в виду: self.input — это текст в начальном фрагменте кода. Понял, понял.

BorrajaX 16.02.2023 20:00

@JohnGordon, это точно мой код: «импортировать tkinter как tk\n\nclass App(tk.Tk):\n def __init__(self):\n super().__init__()\n self.label = tk.Label( self, text = "iets")\n self.label.pack()\n \napp = App()\napp.mainloop()', но тогда менее читабельно

Jasper Bart 16.02.2023 20:03

Похоже, вы пытаетесь сделать что-то подобное code = "import os;print(os.listdir('.'))";exec(code) Но этот код работает, поэтому ваш код должен быть каким-то другим. Мы не сможем помочь, если вы не покажете нам.

John Gordon 16.02.2023 20:05

в своем вопросе я добавил ссылку на свою страницу github. также я добавил метод do для execute.py. и код, который я набрал в своем редакторе. какой код я должен поделиться?

Jasper Bart 16.02.2023 20:07

Первая ссылка на tk — это определение класса class App(tk.Tk): в строке 3, но ошибка в строке 6, так что это очень странно.

John Gordon 16.02.2023 20:09

Я не понимаю, как это может быть фактической строкой кода, потому что отступ неправильный (хотя, возможно, это связано с тем, что сложно правильно отформатировать код в комментарии, особенно для пробелов). Пожалуйста, отредактируйте вопрос и добавьте вывод print(repr(self.input)) туда, где его можно правильно отформатировать.

John Gordon 16.02.2023 20:17

Работал на меня. Пока нет проблем.

toyota Supra 16.02.2023 20:54

Это может быть связано с тем, что вы использовали from tkinter import * в своем основном коде, а exec() по умолчанию выполняет код в текущей области. Попробуйте изменить exec(self.input) на exec(self.input, {}), чтобы входной код выполнялся в своей области. Я бы предложил использовать subprocess.Popen() для выполнения входного кода в другом процессе.

acw1668 17.02.2023 02:03
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
20
63
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ваш файл execute.py разрешает кому-то exec() произвольный код (здесь будут драконы). В этом случае код включает псевдоним tk, который неизвестен в контексте execute.py.

Либо execute.py необходимо импортировать и установить этот псевдоним, либо содержимое текстового файла self.input должно сделать это.

Например:

import statistics

text = """
print(statistics.mean([1,2]))
"""

exec(text)

или

text = """
import statistics
print(statistics.mean([1,2]))
"""

exec(text)

Если ваш текст - это ваш класс, то, похоже, это работает для меня:

text = """
import tkinter as tk

class App(tk.Tk):
    def __init__(self):
        super().__init__()
        self.label = tk.Label(self, text = "iets")
        self.label.pack()
        
app = App()
app.mainloop()
"""

exec(text)

в коде, который я добавил в верхней части моего вопроса: import tkinter as tk. ты это имеешь в виду?

Jasper Bart 16.02.2023 20:10

execute.py не имеет этого импорта. Я не знаю, что такое содержимое self.input, но что бы это ни было, у них тоже нет этого импорта. Поэтому, когда вы пытаетесь exec(self.input) ничего не называть tk.

JonSG 16.02.2023 20:13

self.input совпадает с текстом, который я набрал в своем редакторе, и кодом в верхней части моего вопроса.

Jasper Bart 16.02.2023 20:14

так что import tkinter as tk в моем коде

Jasper Bart 16.02.2023 20:15

ты уверен? Это работает для меня, если я делаю то, что делает мое обновление...

JonSG 16.02.2023 20:18

для меня тоже, но когда я использую остальные мои файлы, это не работает

Jasper Bart 16.02.2023 20:20

Вы обновили pyCharm?

toyota Supra 17.02.2023 10:47
Ответ принят как подходящий

извините за беспокойство, причина моей проблемы была совершенно другой, чем я ожидал! проблема заключалась в том, что когда я ставлю self.input в exec(), программа запускается со всеми глобальными переменными. как исправить? как сказал acw1668: просто используйте exec(self.input, {}) и это сработало! этот пустой dict означает, что в начале выполнения нет глобальных переменных.

поэтому do() становится:

    def do(self):
        sys.stdout.write = output
        try:
            set_last("")
            exec(self.input, {}) # here it's fixed!
        except Exception:
            set_last("text.config(foreground='red')")
            error = traceback.format_exc()
            output(error)

Рад видеть, что вы нашли решение! Тем не менее, будьте очень осторожны, позволяя exec запускаться при вводе пользователем. Вся эта идея вызывает у меня зуд, и ее следует избегать любой ценой в любом виде «производственного» приложения.

JRiggles 17.02.2023 16:18

Другие вопросы по теме