Проблема с python tkinter exec

всего 60 записей tkinter с именами e0, e1 .... e59,60 Метки l0, l1 .... l59. функция отлично работает вот так. Version_one:

def CreateCharacter():
    root.destroy()
    chcreation = tk.Tk()
    global e0, e1,..... e59
    l0 = tk.Label(chcreation, text=char[0],  fg='black')
    l0.grid(row=0, column=0)
    e0 = tk.Entry(chcreation, fg='black')
    e0.grid(row=1, column=0)
    ...........
    e59 = tk.Entry(chcreation, fg='black')
    e59.grid(row=1, column=0)

но если я переключаюсь на метод "exec", как показано ниже, другая функция не может использовать переменные Глобальный e0 e1 .... e59 для сбора входных данных. Version_two:

def CreateCharacter():
    root.destroy()
    chcreation = tk.Tk()
    chcreation.title('create new character')
    chcreation.geometry('1100x500+50+100')
    global e0, e1, ..... e59  
    for i in range(60):
        ro = (i // 11) * 2
        col = i % 11
        exec("l%s=tk.Label(chcreation,text=char[%d])" % (i,i))#char is a name list
        exec("l%s.grid(row=ro,column=col, padx=5, pady=2)" % i)
        exec("e%s=tk.Entry(chcreation, fg='black',width=12)" % i)
        exec("e%s.grid(row=ro+1,column=col, padx=5, pady=2)" % i)

метки и записи хорошо отображаются в окне 'chcreation', но когда другая функция вызвала эту, возникает ошибка «NameError: имя 'e0' не определено». Но я определил их глобально, и в версии Version_one они работают нормально. Пожалуйста посоветуй.

вызывающая функция выглядит так:

def Charater_creating(en):
    crole = []
    for i in range(60):
        exec("crole.append(e%s.get())"%i)
    raw_data = pd.DataFrame(crole, index=mul_index)
    raw_data.to_csv('char.csv',header=False,mode='a')
    for i in range(60):
        exec("e%s.delete(0,'end')"%i)

весь код:

import pandas as pd
import tkinter as tk

array_index = [['Basic', 'Basic' ],['Name', 'Nickname']]
char = array_index[1]
mul_index = pd.MultiIndex.from_arrays(array_index)
role = pd.DataFrame([], index=mul_index)


def CreateCharacter():
    root.destroy()
    chcreation = tk.Tk()
    chcreation.geometry('1200x500+50+100')
    global e0, e1

    #error block
    for i in char:
        t = char.index(i)
        ro = (t // 11) * 2
        col = t % 11
        exec("l%s=tk.Label(chcreation,text=char[%d])" % (t, t))
        exec("l%s.grid(row=ro,column=col, padx=5, pady=2)" % t)
        exec("e%s=tk.Entry(chcreation, fg='black',width=12)" % t)
        exec("e%s.grid(row=ro+1,column=col, padx=5, pady=2)" % t)

    #below is the working block
    # l0 = tk.Label(chcreation, text=char[0], font=('Arial', 12), fg='black')
    # l0['height'] = 2
    # l0['width'] = 8
    # l0.grid(row=0, column=0)
    # e0 = tk.Entry(chcreation, font=('Arial', 10), fg='black')
    # e0['width'] = 8
    # e0.grid(row=1, column=0)
    # l1 = tk.Label(chcreation, text=char[1], font=('Arial', 12), fg='black')
    # l1['height'] = 2
    # l1['width'] = 8
    # l1.grid(row=0, column=1)
    # e1 = tk.Entry(chcreation, font=('Arial', 10), fg='black')
    # e1['width'] = 8
    # e1.grid(row=1, column=1)


    creat_button = tk.Button(chcreation, text='OK', font=('Arial', 8), fg='black')
    creat_button['width'] = 8
    creat_button['height'] = 2
    creat_button.grid(row=11, column=5)
    creat_button.bind('<Button-1>', Charater_creating)


def Charater_creating(en):
    crole = [e0.get(), e1.get()]
    raw_data = pd.DataFrame(crole, index=mul_index)
    raw_data.to_csv('character_data11.csv', header=False, mode='a')
    e0.delete(0, 'end')
    e1.delete(0, 'end')


root = tk.Tk()
root.geometry('900x400+200+50')
c_cbutn = tk.Button(root, text='new', font=('Arial', 20), fg='red', command=CreateCharacter)
c_cbutn['height'] = 2
c_cbutn['width'] = 15
c_cbutn.grid(row=3, column=1)
root.mainloop()

Итак, каков настоящий код в строке global?

figbeam 05.12.2018 10:33

глобальные e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24 , e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, Е50, Е51, Е52, Е53, Е54, Е55, Е56, Е57, Е58, Е59

Biterk 05.12.2018 10:39

Я его просто удалил. Не путаю.

Biterk 05.12.2018 10:41

Что делать, если запись только одна?

Stop harming Monica 05.12.2018 10:42

Хммм, не получается заставить это работать. Можете ли вы опубликовать рабочий код, который мы можем вставить в IDLE и запустить, что вызывает эту проблему. Кроме того, сделайте это только с одной меткой и записью, чтобы оно было коротким ...

figbeam 05.12.2018 10:45

Почему вы все усложняете вместо словарей или списков?

Stop harming Monica 05.12.2018 10:53

Не могли бы вы опубликовать код, который вызывает эту проблему. Не только функции, которые вы опубликовали, но и работающую программу, включая операторы import и mainloop (); что-то, что мы можем вставить прямо в IDLE и запустить.

figbeam 05.12.2018 11:18

@Goyo подход со списком хорош , Я просто не могу понять, почему exec не работает.

Biterk 05.12.2018 16:06

Отправьте минимальный воспроизводимый пример, и, возможно, кто-нибудь сможет вам точно сказать, почему он не работает и как это исправить.

Stop harming Monica 05.12.2018 16:19

@Goyo, Как ты и советовал, выкладываю весь код.

Biterk 06.12.2018 03:47

@figbeam, рабочий код опубликован

Biterk 06.12.2018 03:48
Почему в 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 может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
11
158
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Это может быть проблемой; В коде с exec вы создаете записи с:

exec("e%s_Entry=tk.Entry(chcreation, fg='black',width=12)" % i)

который присваивает виджетам имена: e0_Entry, e1_Entry, ... etc.. Так что имена e0, e1, ... etc. не будут определены.

Дополнительные мысли

Я обнаружил проблему, но не знаю, почему. Рассмотрим функции ниже:

def go_a():
    global a
    a = 25
    print(a)

go_a() # This works just fine


def go_b():
    global b
    exec("b = 25")
    print(b)    

go_b() # Generates NameError: name 'b' is not defined

По какой-то причине функция, которая использует функцию exec, не устанавливает имя «b» в глобальном пространстве имен, если оно там уже не существует. Увидеть ниже:

b = 9   # Setting the name "b"
go_b()  # As if by magic, this now works

Итак, это проблема с exec и прицелом, но я действительно не понимаю, почему.

Я предлагаю вместо этого хранить записи в виде списка или dict, как предлагает Брайан.

Добавлено расследование по exec.

figbeam 06.12.2018 07:25

Никогда не используйте exec для создания переменных. Это делает код практически невозможным для понимания и поддержки.

Если вы хотите создать большое количество виджетов (или объектов любого типа), сохраните их в списке или словаре.

widgets = []
for i in range(60):
    ro = (i // 11) * 2
    col = i % 11
    widget = tk.Label(chcreation,text=i)
    widgets.append(widget)

Теперь вы можете ссылаться на каждую метку с помощью чего-то вроде widgets[0], widgets[1] и т. д. Это хорошо работает, если ваш индекс является целым числом и начинается с нуля.

-или-

widgets = {}
...
widgets[i] = widget

Вышеуказанное работает лучше, когда ваш индекс не является целым числом. Как и в случае со списком, вы по-прежнему ссылаетесь на виджеты таким же образом (например, widgets[0] и т. д.)

подход со списком хорош , Я просто не могу понять, почему не работает exec.

Biterk 05.12.2018 16:19

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