Почему изменение сигналов вызывает NameErrors в здравом коде? - выпуск PyGtk
Я работаю над очень простым приложением для Ubuntu. Я задал вопрос о stackoverflow, и похоже, что проблема, которую я имею, вызвана сигналами, а не областью действия переменных, как я первоначально думал. У меня проблема в том, что когда TextBox
испускает сигнал через activate
весь код работает без сбоев. Но когда я меняю сигнал на insert-at-click
он возвращает NameErrors в каждомTextBox
-связанная функция. Теперь, вполне возможно, что я делаю что-то совершенно не так, но возможно ли, что сигналы могут повлиять на глобальные переменные?
Код в его текущей форме дает мне NameErrors:
def on_servername_insertatcursor(self, widget):
global output
output = StringIO.StringIO()
servername = widget.get_text()
output.write("USHARE_NAME="+servername+'\n')
def on_netif_changed(self, widget):
netif = widget.get_active_text()
global output
output.write("USHARE_IFACE="+netif+'\n')
def on_port_insertatcursor(self, widget):
global output
port = widget.get_text()
output.write("USHARE_PORT="+port+'\n')
def on_telprt_insertatcursor(self, widget):
global output
telprt = widget.get_text()
output.write("USHARE_TELNET_PORT="+telprt+'\n')
def on_dirs_insertatcursor(self, widget):
global output
dirs = widget.get_text()
output.write("USHARE_DIR="+dirs+'\n')
def on_iconv_toggled(self, widget):
global output
iconv = widget.get_active()
if iconv == True:
output.write("USHARE_OVERRIDE_ICONV_ERR="+"True"+'\n')
else:
output.write("USHARE_OVERRIDE_ICONV_ERR="+"False"+'\n')
def on_webif_toggled(self, widget):
global output
webif = widget.get_active()
if webif == True:
output.write("USHARE_ENABLE_WEB="+"yes"+'\n')
else:
output.write("USHARE_ENABLE_WEB="+"no"+'\n')
def on_telif_toggled(self, widget):
global output
telif = widget.get_active()
if telif == True:
output.write("USHARE_ENABLE_TELNET="+"yes"+'\n')
else:
output.write("USHARE_ENABLE_TELNET="+"no"+'\n')
def on_xbox_toggled(self, widget):
global output
xbox = widget.get_active()
if xbox == True:
output.write("USHARE_ENABLE_XBOX="+"yes"+'\n')
else:
output.write("USHARE_ENABLE_XBOX="+"no"+'\n')
def on_dlna_toggled(self, widget):
global output
dlna = widget.get_active()
if dlna == True:
output.write("USHARE_ENABLE_DLNA="+"yes"+'\n')
else:
output.write("USHARE_ENABLE_DLNA="+"no"+'\n')
def on_commit_clicked(self, widget):
commit = output.getvalue()
logfile = open('/home/boywithaxe/Desktop/ushare.conf','w')
logfile.write(commit)
def on_endprogram_clicked(self, widget):
sys.exit(0)
1 ответ
Вы неправильно понимаете значение global
заявление в Python. Вот что говорится в документации по Python:
Глобальный оператор... означает, что перечисленные идентификаторы должны интерпретироваться как глобальные. Было бы невозможно назначить глобальную переменную без глобальной, хотя свободные переменные могут ссылаться на глобальные переменные, не будучи объявленными глобальными.
Так что, в основном, вам нужно всего лишь использовать global blah
когда вам нужно назначить глобальную переменную с именем blah
, Однако эта переменная уже должна существовать в глобальной области видимости. Если вы просто обращаетесь к глобальной переменной или ее методам (в отличие от присвоения ей), вам не нужно объявлять ее как global
,
Так что вам нужно что-то вроде
output = None
def on_servername_insertatcursor(self, widget):
global output
output = StringIO.StringIO()
servername = widget.get_text()
output.write("USHARE_NAME="+servername+'\n')
def on_netif_changed(self, widget):
netif = widget.get_active_text()
output.write("USHARE_IFACE="+netif+'\n')
...
Однако весь подход с использованием глобальной переменной и зависимостью всего от порядка вызовов функций (on_servername_insertatcursor ДОЛЖЕН быть вызван первым, в противном случае другие функции потерпят неудачу) не является хорошей практикой кодирования.
ОБНОВЛЕНИЕ: Кроме того, мне пришло в голову, что функции, которые вы показываете, на самом деле являются методами класса, не так ли? В этом случае вы можете сделать output
член класса и доступ к нему как self.output
:
class MyApp(gtk.Window):
output = None
def __init__(...):
...
self.output = StringIO.StringIO()
def on_servername_insertatcursor(self, widget):
servername = widget.get_text()
self.output.write("USHARE_NAME="+servername+'\n')
def on_netif_changed(self, widget):
netif = widget.get_active_text()
self.output.write("USHARE_IFACE="+netif+'\n')
Тем не менее, вывод вашего приложения зависит от порядка нажатия кнопок пользователем, что не круто. Например, если пользователь дважды щелкнет по флажку "dlna", в конфиге будет 2 строки, которые, я полагаю, не то, что вы хотите.