How to change global variable using other file by importing - python

I have made this calculator on Python with GUI using Tkinter, it's my university project but there are some requirements and one is that every function should be imported in the main GUI file not to be placed there.
For example, I have created a null operator textinput for textvariable and buttons from 1 to 9 and defined a button click handler function for it:
def btnClick(numbers):
global operator
operator=operator+str(numbers)
text_Input.set(operator)
And I have saved this in the other file called "Buttons.py"
Now when i call it in my gui file like this and make a button to execute it
import Buttons
button7=Button(cal,padx=16,bd=4,fg='black',font=('The Citadels',20),
text='7',command=lambda:Buttons.btnClick(7),bg='ghost white')
.grid(row=5,column=0)
But get an error saying
name 'operator' is not defined
What is missing for my code to work ?

When you use the import statement on its own, you import the module but you don't import the namespace. operators is not defined because it is part of the module's namespace. To fix this, you can either use Buttons.operator instead of operator, or you can change your import statement to look like from Buttons import *, which will import all the variables from Buttons into your namespace as well.

Related

How to import another python file as many times as the button is pressed in tkinter?

def addstudent():
import add_student
b1= Button(root, text="Add Student",width=35,font=("Times New Roman",15),command=addstudent)
b1.place(relx=0.5,rely=0.24,anchor=CENTER)
I was trying to import add_student as many times as the button is pressed. When button is pressed first time the function addstudent imports add_student file. But when button is pressed next time that function don't imports add_student file.
I'm not sure what kind of result this would do but I think you want
you call to add_student to have some kind of "side-effect" (add a row to a database, add an element to a list, ...).
It's true that sometimes importing a name will have side effects but
this might now be the case.
You most likely have to call the function using the name you have imported
such as in the following code.
def addstudent():
import add_student # make the name add_student visible in the function
add_student() # call the function and possibly do some work, including side-effects

how to use functions of other .py modules in a GUI (tkinter) module in the same namespace?

I am new in tkinter please help me out .
I have implemented a module(PDF2Text.Py) that its class has a function (convert_pdf_to_txt(path)) that takes a path of a pdf file and converts the pdf file into text.
I also implemented another module(TopicModeling.py) that its class has a function (creat_LDA_model(text)) that takes a text and do topic modeling on the text.
Now, I want the tkinter GUI that is, upon clicking the "Browse" button it browses the path with filedialog.askopenfilename and its command function send the given path to convert_pdf_to_txt(path) function of PDF2Text.Py.
Then by clicking the "Model" button, its command function returned text should be sent to creat_LDA_model(text) function in TopicModeling.py and show the result in an Entry widget or any other widget types .
I would like to know the structure of the GUI module;
how to call or get and set the parameters to other modules/functions from the GUI module in command functions of the buttons.
thanks
Seems like you have multiple questions here. I believe one of them is how to start askopenfilename in a particular folder. Once the file name is returned, i can be passed to another function.
fname = askopenfilename(initialdir = r'c:\somepath', filetypes=(("Statement files", "*.pdf"),))
To call other functions you have written, import the module, let's cal it ReadPdf.py, use something like this.
import ReadPdf
PdfOut = ReadPdf.ReadPDFData(fname)
CCStmtTxns = ReadPdf.ReadPDFData(CreditCardPDFDataPathandFile)

Understanding import and scope

I am a noob to python and I am trying to understand how the import statement works.
I am running python 3.6.
I have IDLE working.
My test directory is setup like
directory:test_py
In the directory test_py I have files
test_calc.py,button.py,graphics.py
graphics.py is a graphics library.
My main program is in test_calc.py.
In test_calc.py I use from graphics import *. Its the first line
button.py is a module that contains a class definition, Button.
It also uses the graphics library graphics.py.
The main program in test_calc.py uses the Button class.
The Button class definition also calls Point, a function from the graphics library.
I thought the call to create a Button object would be able to use the graphcs
library from the statement from graphics import* in test_calc.py, but it cant.
button.py also needs a from graphics import * to access the graphics library functions.
Is there a way I can have just the **from graphics import* ** in test_calc.py
and have the Button class also see the graphics library
module and objects without have to also import it in button.py?
I have spent a easy 8hrs reading and trying to figure this out.
Any help is appreciated.
here is the complete test_calc.py file
from graphics import *
from button import *
def __createButtons(win):
#create a list of buttons
bSpecs = [(2,1,'0'), (3,1,'.'),
(1,2,'1'), (2,2,'2'), (3,2,'3'), (4,2,'+'), (5,2,'-'),
(1,3,'4'), (2,3,'5'), (3,3,'6'), (4,3,'*'), (5,3,'/'),
(1,4,'7'), (2,4,'8'), (3,4,'9'), (4,4,'<-'), (5,4,'C')]
buttons = []
for (cx,cy,label) in bSpecs:
buttons.append(Button(win, Point(cx,cy), .75,.75,label))
###create larger = button
buttons.append(Button(win, Point(4.5,1), 1.75, .75, "="))
#activate all buttons
for b in buttons:
b.activate()
def main():
#create the window for the calculator
win = GraphWin("Calculator")
win.setCoords(0,0,6,7)
win.setBackground("slategray")
win= win
__createButtons(win)
main()
here is the beginning of button.py
The Point function from graphics library is not available to Button without this statement
from graphics import *
class Button:
def __init__(self, win, center, width, height, label):
w,h = width/2.0, height/2.0
x,y = center.getX(), center.getY()
self.xmax, self.xmin = x+w, x-w
self.ymax, self.ymin = y+h, y-h
#Point function from graphics library
p1 = Point(self.xmin,self.ymin)
p2 = Point(self.xmax, self.ymax)
Short answer: No, there is no way to do that.
graphics.py is out of scope of button.py, because test_calc.py imported graphics and test_calc.py is in scope of button.py.
However, if you really want to save an extra line, you can just remove from graphics import * from test_calc.py because button.py already imported graphics.py.
No, you can't do this. If this worked the way you want, you'd break namespacing and scope implicitly within button, not just explicitly in test_calc.
The scope of a module (used by all things defined in that module) is defined by what it imports, and what it defines (and in poor design cases, by things monkey=patched in later). Adding in things from "stuff defined in the things that imported me" is a terrible idea.
The correct solution here is to just do:
# If a package, explicit relative imports avoid checking the whole of sys.path
from .graphics import *
# IF not a package, use plain names without leading .s
from graphics import *
at the top of your button.py file, so it actually specifies where it expects to get the APIs from (ideally, you explicitly list the names to use, not just *, which helps static checking code determine if all your names are defined, helps maintainers figure out where specific names came from, and avoids the risk of two modules providing the same name and stomping all over each other). Since you've already done this, you're golden; you can just omit the import of graphics stuff in test_calc.py (assuming test_calc.py itself doesn't use it).
If, for some insane reason, this really is necessary, the simplest way to do it is to bypass import semantics and explicitly eval the code for button in the same scope that includes the graphics stuff. In test_calc.py, after doing from graphics import *, you'd explicitly open and read the contents of button.py (into, for example, button_source) then do:
eval(compile(button_source, button_path, 'exec'), globals())
which would compile and evaluate the source code of button.py using test_calc's global scope (which includes graphics stuff now), so the newly defined stuff would be defined in test_calc's globals, and see all the stuff defined there as its "native scope" too.

Python Circular dependencies, unable to link variable to other file

I am working on a program that allows me to directly edit a word document through a tkinter application. I am trying to link the tkinter input from my gui file to my main file so that I can execute my docx functions. When I try to execute my code this way, it tells me that entry in entry.get() is not defined. When I try to import this from main, I receive a circular import error.
main.py
from docx import Document
from docx.shared import Inches
import os
os.chdir("\\Users\\insanepainz\Desktop")
doc = Document('TemplateTest.docx')
paragraphs = doc.paragraphs
def WebsiteChange():
website = entry.get()
print(website)
master.quit()
for paragraph in doc.paragraphs:
if '^website' in paragraph.text:
paragraph.text = gui.entry
print(paragraph.text)
doc.save(doc)
pass
gui.py
import main
from tkinter import *
master = Tk()
#------------Web Entry Window
Label(master, text="Website Name: ").grid(row=0, sticky=W)
entry = Entry(master)
entry.grid(row=0, column=1)
# Connect the entry with the return button
submit = Button(master, text="Submit", command=main.WebsiteChange)
submit.grid(row=1)
# Centers the program window
master.eval('tk::PlaceWindow %s center' % master.winfo_pathname(master.winfo_id()))
mainloop()
I have been struggling to understand this concept for awhile. Circular errors are giving me a headache. Any help would be greatly appreciated.
The import mechanism is designed to allow circular imports. But one must remember the following:
The name of the main module created from the startup script is __main__, rather than as its filename minus .py. Any other file importing the startup script must import __main__, not import filename. (Otherwise, a second module based on the startup script will be created with its normal name.)
Execution of the code in a module is paused at each import. The order of initial imports is important as the last module in the chain is the first to be run to completion. Each object within modules must be available when the reference is executed. References within function definitions are not executed during the import process.
Applying the above to your pair, I assume that gui.py is the startup script. Python will immediate create an empty module object as the value of sys.modules['__main__']. Somain.pyshould importgui.pywithimport main as gui(the name change is just for convenience). Within the function definition, you should be able to usegui.entrywithout problem since there will be no attempt to lookupgui.entryuntil the function is called. I suggest addingentry = gui.entryas the first line of the function and usingentry` in the two places needed.
The following pair of files run as desired when tem2.py is run.
# tem2.py
import tem3
a = 3
print(tem3.f())
# tem3.py
import __main__ as tem2
def f():
return tem2.a
Move the definition of entry into a third file and import it in both files.
You can pass the entry to WebsiteChange:
def WebsiteChange(entry):
website = entry.get()
submit = Button(master, text="Submit",
command=lambda e=entry: main.WebsiteChange(e))

Seems like python is partial

The following is a function I created, and put it in a file called last_function.py
from tkinter import*
def new_gui(app,sound_file,mixer):
track=mixer.Sound(sound_file)
def track_toggle():
if ballCheckbutton.get()==1:
track.play(loops=-1)
else:
track.stop()
ballCheckbutton=IntVar()
c1=Checkbutton(app,text="check me out",command=track_toggle,variable=ballCheckbutton)
c1.pack(side=LEFT)
ballScale=DoubleVar()
def ScaleVolume(v):
track.set_volume(ballScale.get())
ballScale.set(track.get_volume())
s1=Scale(app,variable=ballScale,resolution=0.1,command=ScaleVolume,orient=HORIZONTAL,from_=0.0,to=1.0,label="volume")
s1.pack()
and this is the file i use.. to call the code and run it..
from tkinter import *
import pygame.mixer
from last_function import*
app=Tk()
mixer=pygame.mixer
mixer.init()
new_gui(app,"49119_M_RED_HardBouncer.wav",mixer)
def close():
mixer.stop()
app.destroy()
app.protocol("WM_DELETE_WINDOW",close)
app.mainloop()
Everything works fine.. but my query is...
1> Why can't I remove from tkinter import* from the last_function file.. cause anyway it's got that on the top of the file that's calling it right. Why do I get an error saying IntVar() not defined.
2> Why do I have to pass mixer as a parameter in the function? can the function not inherit it directly from import pygame.mixerthat's on top of the file calling it?
What I mean to say is. THERE ARE TKINTER COMPONENTS ALSO BEING USED, BUT I DON'T PASS TKINTER AS A PARAMETER.. Do I ! then why is there this... selective parameter assignment??
I'm really confused!!!
1> Why can't i remove from tkinter
import* from the last_function file..
cause anyway it's got that on the top
of the file that's calling it
right.Why do i get an error saying
IntVar() not defined
The Python "import" follows the same scoping rules as the rest of the Python language. By "import" at the top of your second files does not make the Tkinter namespace available to the last_function.py module. Tkinter also needs to be imported there.
2>why do i have to pass mixer as a
parameter in the function? can the
function not inherit it directly from
import pygame.mixerthat's on top of
the file calling it? WHAT I MEAN TO
SAY IS. THERE ARE TKINTER COMPONENTS
ALSO BEING USED,BUT I DON'T PASS
TKINTER AS A PARAMETER.. DO I!! then
why is there this.. selective
parameter assignment??
With the way you have this coded, you need to pass mixer because you are modifying it in your second file with:
mixer.init()
If you reimported mixer in your last_function.py, you would be getting another instance of mixer and not the one previously imported. There is nothing selective about this since both of your files have the Tkinter namespace imported.
You should try and re-factor this code to avoid having to import Tkinter into two modules and having to init mixer in one module and pass it to another.

Categories

Resources