How to re-execute a file - python

I am trying to re-execute a file's code within the program
main.py
# Within the main.py
exec(open('PDM/Path2.py').read())
PDM/Path2.py
# Within the file being read
import tkinter as tkin
class path2_wind:
def __init__(self):
self.path2 = tkin.Tk()
self.path2.geometry('400x430')
self.path2.title('PDM/Path_2')
self.sight = tkin.PhotoImage(file='PDM/Path_2.Sight.png')
self.back = tkin.Label(self.path2,image=self.sight)
self.back.pack(side='top')
self.frame = tkin.Frame(self.path2)
self.hello = tkin.Label(self.frame,text='Welcome User (Name Here)')
self.back = tkin.Button(self.frame,text='Back',command = self.path2.destroy)
self.frame.pack(side='top')
self.hello.pack(side='left')
self.back.pack(side='left')
tkin.mainloop()
open = path2_wind()
The error displayed is TypeError: 'path2_wind' object is not callable.

It is because you have override the standard function open() by the line:
open = path2_wind()
So when the following code is being executed again:
exec(open('PDM/Path2.py').read())
it raises the exception since open is not the standard function now.
Use other name instead of open, for example:
win = path2_wind()
As #TheLizzard stated in the comment, it is better to use import instead of exec():
main.py
from PDM.Path2 import path2_wind
win = path2_wind()
...
PDM/Path2.py
import tkinter as tkin
class path2_wind:
def __init__(self):
self.path2 = tkin.Tk()
self.path2.geometry('400x430')
self.path2.title('PDM/Path_2')
#self.sight = tkin.PhotoImage(file='PDM/Path_2.Sight.png')
self.sight = tkin.PhotoImage(file='images/nier-a2.png')
self.back = tkin.Label(self.path2,image=self.sight)
self.back.pack(side='top')
self.frame = tkin.Frame(self.path2)
self.hello = tkin.Label(self.frame,text='Welcome User (Name Here)')
self.back = tkin.Button(self.frame,text='Back',command = self.path2.destroy)
self.frame.pack(side='top')
self.hello.pack(side='left')
self.back.pack(side='left')
tkin.mainloop()
if __name__ == '__main__':
win = path2_wind()

Related

Python code to get multiple input from a pop up window and reuse it

I'm trying to write a piece of code that gets input from the user and is then passed to multiple pieces of programs that do certain operations.
Below is the code I'm using, For a trial, I'm getting the input and trying to print it outside the function which throws an error as 'Input_Path' is not defined.
Could somebody help me out here?
import tkinter as tk
import openpyxl
class App(tk.Frame):
def __init__(self,master=None,**kw):
#Create a blank dictionary
self.answers = {}
tk.Frame.__init__(self,master=master,**kw)
tk.Label(self,text="Give Input Sheet Path").grid(row=0,column=0)
self.question1 = tk.Entry(self)
self.question1.grid(row=0,column=1)
tk.Label(self,text="Give Output Sheet Path").grid(row=1,column=0)
self.question2 = tk.Entry(self)
self.question2.grid(row=1,column=1)
tk.Button(self,text="Feed into Program",command = self.collectAnswers).grid(row=2,column=1)
def collectAnswers(self):
self.answers['Input_Path'] = self.question1.get()
self.answers['Output_Path'] = self.question2.get()
Input_Path = self.answers['Output_Path']
Output_Path = self.question2.get()
functionThatUsesAnswers(self.answers)
def functionThatUsesAnswers(answers):
print("Given Input Path ", answers['Input_Path'])
print("Given Output Path ", answers['Output_Path'])
quit()
def quit():
root.destroy()
if __name__ == '__main__':
root = tk.Tk()
App(root).grid()
root.mainloop()
print(Input_Path)
wb = openpyxl.load_workbook(f'r"{Input_Path}"') # trying to open the input sheet from the below path
#wb = openpyxl.load_workbook(r"C:\Users\xx'x\xx.x\Input_Sheet.xlsx")
Because the Input_path is defined in method and you are calling the path outside the Class so it cant access it, one solution is make that Input_path as Global so it can be called outside

Get selected object from ListBox (binded to ListStore) in Python GTK

I have made a simple GTK music player with ListBox (as playlist).
This is GObject class, which i use to bind to ListBox (using bind_model() method) and ListStore.
import eyed3
from gi.repository import Gio, GObject
class Song(GObject.GObject):
path = GObject.Property(type=str)
name = GObject.Property(type=str)
def __init__(self, path):
GObject.GObject.__init__(self)
self.path = path
self.file = eyed3.load(path)
self.name = self
def __str__(self):
return str(self.file.tag.artist) + ' - ' + str(self.file.tag.title)
playlist = Gio.ListStore().new(Song)
And this is how I bind ListStore to ListBox:
play_listbox.connect('row-selected', self.on_row_selected)
playlist.append(Song('/home/user/Downloads/Some album/01 - Song1.mp3'))
playlist.append(Song('/home/user/Downloads/Some album/02 - Song2.mp3'))
play_listbox.bind_model(playlist, self.create_song_label)
def create_song_label(self, song):
return Gtk.Label(label=song.name)
And so far, everything works like it should.
The question is: Is it possible to retrieve Song object (stored in playlist) based on selection? To retrieve path property stored in that object?
If not, is it possible to at least retrieve selection text? Trying this with
def on_row_selected(self, container, row):
print(row.widget.label)
Gives a traceback:
Traceback (most recent call last):
File "/home/user/Documents/App/player.py", line 45, in on_row_selected
print(row.widget.label) # or data, value, text - nothing works
RuntimeError: unable to get the value
row variable is of type
<Gtk.ListBoxRow object at 0x7f9fe7604a68 (GtkListBoxRow at 0x5581a51ef7d0)>
So above code, I think, should work like a charm... but it doesn't.
Thank you very much for any help provided!
So you need to assign the selection with:
treeview_selection = treeview.get_selection()
And connect it with the 'changed' signal:
treeview_selection.connect('changed', on_tree_selection_changed)
Then you can fetch the required data with:
def on_tree_selection_changed(self, treeview):
model, treeiter = treeview.get_selected()
if treeiter is not None:
print(model[treeiter][0]) # you should a list index to get the data you require for each row - first column = [0], second column = [1] etc.
I would suggest you read the pgi docs and also the python Gtk docs
Is it possible to retrieve Song object (stored in playlist) based on selection? To retrieve path property stored in that object?
def on_row_selected(self, container, row):
song = playlist.get_item(row.get_index())
If not, is it possible to at least retrieve selection text?
def on_row_selected(self, container, row):
name = row.get_child().get_text()
Here is an example. You could also use the selected-rows-changed signal if you have to deal with multiple selections:
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gio, GObject
import sys
class Song(GObject.GObject):
path = GObject.Property(type=str)
name = GObject.Property(type=str)
def __init__(self, path, name):
GObject.GObject.__init__(self)
self.path = path
self.name = name
class GUI:
def __init__(self):
self.playlist = Gio.ListStore()
self.playlist.append(Song("path1", "name1"))
self.playlist.append(Song("path2", "name2"))
self.playlist.append(Song("path3", "name3"))
play_listbox = Gtk.ListBox()
play_listbox.set_selection_mode(Gtk.SelectionMode.SINGLE)
play_listbox.bind_model(self.playlist, self.create_widget_func)
play_listbox.connect('row-selected', self.on_row_selected_1)
play_listbox.connect('row-selected', self.on_row_selected_2)
play_listbox.connect('selected-rows-changed', self.on_selected_rows_changed)
window = Gtk.Window()
window.add(play_listbox)
window.connect("destroy", self.on_window_destroy)
window.show_all()
def create_widget_func(self, song):
return Gtk.Label(label = song.name)
def on_row_selected_1(self ,container, row):
print("on_row_selected_1")
song = self.playlist.get_item(row.get_index())
print(song.path)
def on_row_selected_2(self ,container, row):
print("on_row_selected_2")
print(row.get_child().get_text())
def on_selected_rows_changed(self, container):
print("on_selected_rows_changed", len(container.get_selected_rows()), "item(s) selected")
for row in container.get_selected_rows():
song = self.playlist.get_item(row.get_index())
print(song.name, song.path)
print("---")
def on_window_destroy(self, window):
Gtk.main_quit()
def main():
app = GUI()
Gtk.main()
if __name__ == "__main__":
sys.exit(main())

Data from child window

In the imported code, the variable 'values' is set correctly with the date selected by the user.
The def selection is called at the exit of the calendar.
I'm stuck. I don't know how to catch it and use it in my main code.
Thanks a lot.
# MAIN CODE (simplified)
from tkinter import *
import calendarWidget
def manageCalendarWindow():
root4 = Tk()
data = {}
app = calendarWidget.Calendar(root4, data)
root4.mainloop()
manageCalendarWindow()
#how to get the date?
-.-.-.-.-.-.-.
# CALENDAR WIDGET (simplified)
class Calendar:
def setup(self, y, m)
(...)
for w, week in enumerate(self.cal.monthdayscalendar(y, m), 2):
for d, day in enumerate(week):
if day:
b = tk.Button(self.parent, width=1, text=day, relief = 'flat',\
command=lambda day=day:self.selection(day, calendar.day_name[(day-1) % 7]))
self.wid.append(b)
b.grid(row=w, column=d)
def selection(self, day, name):
self.day_selected = day
self.month_selected = self.month
self.year_selected = self.year
self.day_name = name
#data
self.values['day_selected'] = day
self.values['month_selected'] = self.month
self.values['year_selected'] = self.year
self.values['day_name'] = name
self.values['month_name'] = calendar.month_name[self.month_selected]
self.setup(self.year, self.month)
print(self.values) # <--- here the value is correct
self.parent.destroy()
-.-.-.-.-.-.-.-
THIS WORKS:
def manageCalendarWindow():
root4 = Tk()
data = {}
app = calendarWidget.Calendar(root4, data)
root4.mainloop()
return app
app=manageCalendarWindow()
print(app.year_selected,app.month_selected,app.day_selected)
THIS NOT:
class enterWindows():
def B_CalendarWindow(self):`
app=self.manageCalendarWindow()
print("year: ",app.year_selected)
print("and... this will never be printed!")
def manageCalendarWindow(self):
root4 = Tk()
data = {}
app = calendarWidget.Calendar(root4, data)
root4.mainloop()
return app
Everything local to the function manageCalendarWindow() is garbage collected when the function exits. This includes app (the class instance). You would have to return it to keep it alive. Note also that there is no self.month in the code you posted but I assume that comes from cutting the amount of code back for this post.
def manageCalendarWindow():
root4 = Tk()
data = {}
app = calendarWidget.Calendar(root4, data)
root4.mainloop()
return app
## or
## return app.day_name
app=manageCalendarWindow()
print(app.day_name)
## or
##day_name=manageCalendarWindow()
##print(day_name)
A simple proof-of concept program that gets a variable from a class instantiated within the class.
class SubClass():
def __init__(self):
self.variable="SubClass variable"
class MainClass():
def __init__(self):
app=self.instantiate_class()
print(app.variable) ## prints the string
def instantiate_class(self):
app=SubClass()
print("app =", app) ## not empty
return app
MainClass()
As mentioned in my comments, there can be only one mainloop in the code. The others will be simply ignored. So it's not possible to use it to wait for a response from a child window.
The solution I used is
app = myCalendar.Calendar(personal_path, root4, gui_language)
root4.wait_window(app.parent)
return app
The code opens the window and waits the result using wait_window().
Thanks all.
Ciao.

NSMenuItem + Python + Dynamic Variables

I'm trying to get a dynamic label for a menu item in this. I've written the entire app in Python but honestly with how much NSMenuItem looks, I might as well rewrite it in Objc...
import objc
from Foundation import *
from AppKit import *
from PyObjCTools import AppHelper
class MyApp(NSApplication):
def finishLaunching(self):
# Make statusbar item
statusbar = NSStatusBar.systemStatusBar()
self.statusitem = statusbar.statusItemWithLength_(NSVariableStatusItemLength)
self.icon = NSImage.alloc().initByReferencingFile_('icon.png')
self.icon.setScalesWhenResized_(True)
self.icon.setSize_((20, 20))
self.statusitem.setImage_(self.icon)
#make the menu
self.menubarMenu = NSMenu.alloc().init()
self.menuItem = NSMenuItem.alloc().initWithTitle_action_keyEquivalent_('Click Me', 'clicked:', '')
self.menubarMenu.addItem_(self.menuItem)
self.quit = NSMenuItem.alloc().initWithTitle_action_keyEquivalent_('Quit', 'terminate:', '')
self.menubarMenu.addItem_(self.quit)
#add menu to statusitem
self.statusitem.setMenu_(self.menubarMenu)
self.statusitem.setToolTip_('My App')
def clicked_(self, notification):
NSLog('clicked!')
if __name__ == "__main__":
app = MyApp.sharedApplication()
AppHelper.runEventLoop()
Did you try setTitle_?
def clicked_(self, notification):
self.menuItem.setTitle_("Clicked!")
or with a timer:
def finishLaunching(self):
# ...
self.timer = NSTimer.alloc().initWithFireDate_interval_target_selector_userInfo_repeats_(NSDate.date(), 1.0, self, 'tick:', None, True)
NSRunLoop.currentRunLoop().addTimer_forMode_(self.timer, NSDefaultRunLoopMode)
self.timer.fire()
def tick_(self, arg):
self.menuItem.setTitle_("Tick %d!" % int(time.time()))
For live updates you probably need JGMenuWindow (SO: How to update NSMenu while it's open?)

Problem with defining variables in python

I'm trying to write some xml by this piece of code
docs = XmlReportGenerator()
docs.AddMatchRow('FC Barcelona','Madryt','5:0')
docs.Save()
and I wrote my own method:
from lxml import etree
class XmlReportGenerator:
""""""
root = etree.Element('results')
doc = etree.ElementTree(root)
#----------------------------------------------------------------------
def __init__(self):
""""""
def AddMatchRow(self,teamA,teamB, score):
pageElement = etree.SubElement(root,'Flight',teamA, teamB, score)
""""""
def Save(self,path = None):
outFile = open('Matches.xml', 'w')
doc.write(outFile)
NameError: global name 'root' is not defined
Process terminated with an exit code of 1
done
NameError: global name 'doc' is not defined
Process terminated with an exit code of 1
done
Am I missing something? I'm a newbie in python (I have more experience in c#).
Python is explicit. Instance variables must be prepended with self.. Class variables must be prepended with then name of the class.
Here's a fixed version. The original SubElement call was incorrect as well:
from lxml import etree
# derive from 'object' if Python 2.X (it is default in Python 3.X)
class XmlReportGenerator(object):
def __init__(self):
# clearer to init instance variables here.
self.root = etree.Element('results')
self.doc = etree.ElementTree(self.root)
def AddMatchRow(self,teamA,teamB, score):
# Need self.root here
pageElement = etree.SubElement(self.root,'Flight')
# Added data elements (or did you want attributes?)
etree.SubElement(pageElement,'teamA').text = teamA
etree.SubElement(pageElement,'teamB').text = teamB
etree.SubElement(pageElement,'score').text = score
def Save(self,path = None):
outFile = open('Matches.xml', 'w')
# Need self.doc here
self.doc.write(outFile)
# This code will run if the script is executed directly,
# but will be skipped if the script is imported by another script.
if __name__ == '__main__':
docs = XmlReportGenerator()
docs.AddMatchRow('FC Barcelona','Madryt','5:0')
docs.Save()
self is there for a reason. Use self.root, not root

Categories