Я делаю редактор кода. Но когда я набираю в своем редакторе кода следующий код, он получает 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 и так далее.
выполнить.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
заранее спасибо!
когда я покажу вам все свои 8 файлов, мой вопрос станет не совсем ясным
загляните в мой репозиторий на github, там вы можете увидеть весь мой проект
когда я покажу вам все свои 8 файлов, мой вопрос станет не совсем ясным. Тогда сделайте его небольшую версию, содержащую только код, который является критическим для этой ошибки.
Если я нажму на ссылку на ваш репозиторий github, я получу ошибку 404 (это случайно не частный репозиторий?). Кроме того, имейте в виду, что идея Stackoverflow заключается в том, что вопросы автономны и не зависят от внешних ссылок, которые могут измениться или исчезнуть. В основном, если кто-то найдет вопрос в будущем, он сможет понять всю проблему (и, надеюсь, решение)
Большинство людей не хотят переходить по какой-либо внешней ссылке и копаться в горах кода, чтобы помочь вам решить вашу проблему. Ваша задача — дать нам небольшой (но полный) пример.
@BorrajaX, извините, я опубликую свой репозиторий
Есть ли шанс, что где-то в вашем проекте есть файл с именем tkinter
или tk
, который вызывает конфликт?
я уверен, что у меня нет файла с именем tkinter
exec
будет запускать текст как Python. Этот текст (значение: self.input
) где-то содержит tk
?
self.input
— это текст, который я набрал в своем редакторе кода, см. начало моего вопроса.
Покажите нам точный вывод этого кода: print(repr(self.input))
вы можете добавить эту строку вверху do()
О, я понимаю, что вы имеете в виду: self.input — это текст в начальном фрагменте кода. Понял, понял.
@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()', но тогда менее читабельно
Похоже, вы пытаетесь сделать что-то подобное code = "import os;print(os.listdir('.'))";exec(code)
Но этот код работает, поэтому ваш код должен быть каким-то другим. Мы не сможем помочь, если вы не покажете нам.
в своем вопросе я добавил ссылку на свою страницу github. также я добавил метод do для execute.py. и код, который я набрал в своем редакторе. какой код я должен поделиться?
Первая ссылка на tk
— это определение класса class App(tk.Tk):
в строке 3, но ошибка в строке 6, так что это очень странно.
Я не понимаю, как это может быть фактической строкой кода, потому что отступ неправильный (хотя, возможно, это связано с тем, что сложно правильно отформатировать код в комментарии, особенно для пробелов). Пожалуйста, отредактируйте вопрос и добавьте вывод print(repr(self.input))
туда, где его можно правильно отформатировать.
Работал на меня. Пока нет проблем.
Это может быть связано с тем, что вы использовали from tkinter import *
в своем основном коде, а exec()
по умолчанию выполняет код в текущей области. Попробуйте изменить exec(self.input)
на exec(self.input, {})
, чтобы входной код выполнялся в своей области. Я бы предложил использовать subprocess.Popen()
для выполнения входного кода в другом процессе.
Ваш файл 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
. ты это имеешь в виду?
execute.py не имеет этого импорта. Я не знаю, что такое содержимое self.input
, но что бы это ни было, у них тоже нет этого импорта. Поэтому, когда вы пытаетесь exec(self.input)
ничего не называть tk
.
self.input совпадает с текстом, который я набрал в своем редакторе, и кодом в верхней части моего вопроса.
так что import tkinter as tk
в моем коде
ты уверен? Это работает для меня, если я делаю то, что делает мое обновление...
для меня тоже, но когда я использую остальные мои файлы, это не работает
Вы обновили pyCharm?
извините за беспокойство, причина моей проблемы была совершенно другой, чем я ожидал! проблема заключалась в том, что когда я ставлю 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
запускаться при вводе пользователем. Вся эта идея вызывает у меня зуд, и ее следует избегать любой ценой в любом виде «производственного» приложения.
Сообщение об ошибке относится к строке 24, которой явно нет в этом коде. Покажи нам свой реальный код.