Cannot import Tkinter font object from module - python-2.7

I've got a feeling this will end in a facepalm, but I just can't puzzle out why this import x from y scenario isn't working for me. As a starting point, take the following module main.py:
import Tkinter as tk
import tkFont
__metaclass__ = type
#Create widgets
root = tk.Tk()
fntPlainText = tkFont.Font(family='Courier New',size=10)
lblDisplay = tk.Label(root, relief=tk.SUNKEN,
font=fntPlainText,
width=30,height=5,
text='This is a test!')
#Do layout
lblDisplay.grid(padx=5,pady=5)
#Begin app
tk.mainloop()
This runs normally and puts up a small label with the expected content:
So now I want to move the definition of this Font object to a separate module, so I can share it among multiple applications. My updated code modules are fonts1.py:
import Tkinter as tk
import tkFont
__metaclass__ = type
fntPlainText = tkFont.Font(family='Courier New',size=10)
...and main1.py:
import Tkinter as tk
from fonts1 import fntPlainText
__metaclass__ = type
#Create widgets
root = tk.Tk()
lblDisplay = tk.Label(root, relief=tk.SUNKEN,
font=fntPlainText,
width=30,height=5,
text='This is a test!')
#Do layout
lblDisplay.grid(padx=5,pady=5)
#Begin app
tk.mainloop()
But when I run main1.py, I get a traceback:
Traceback (most recent call last):
File "G:\Python\experiments\investigations\tk\main1.py", line 2, in <module>
from fonts1 import fntPlainText
File "G:\Python\experiments\investigations\tk\fonts1.py", line 5, in <module>
fntPlainText = tkFont.Font(family='Courier New',size=10)
File "C:\Python27\lib\lib-tk\tkFont.py", line 89, in __init__
tk.call("font", "create", self.name, *font)
AttributeError: 'NoneType' object has no attribute 'call'
From Googling and experimenting, I found enough to know that something's going wrong with the assignment of fntPlainText, but (again) I can't figure out what it is. The biggest puzzle of the whole situation is that when I pare down fonts1.py to simply define fntPlainText as a tuple--
Modified fonts1.py:
fntPlainText = ('Courier New',10)
Running main1.py now completes normally and paints the same window as main.py.
If it matters, the environment is Python 2.7.x running on Windows 7.

You need to create a root window (tk.Tk()) before creating the font. If you move your
from fonts1 import fntPlainText
below the tk.Tk() call it should work as you expect.

Related

Attribute error in simpledialog module in Python 2

I have to create popup dialog box which contains text field using tkinter module in Python 2(not Python 3). My other program has many Python2 modules(I have written whole code in Python 2) and so I can't go for Python 3. Here is my code which works fine in Python 3 but not in Python 2.
from tkinter import simpledialog
from tkinter import *
def s():
print(simpledialog.askstring("hai","inp"))
root = Tk()
b = Button(root, text="popup",command=s)
b.pack()
root.geometry("400x400")
root.mainloop()
This is the error :
Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 1550, in __call__
return self.func(*args)
File "popup.py", line 4, in s
print(simpledialog.askstring("hai","inp"))
AttributeError: 'module' object has no attribute 'askstring'
Please mention any alternatives to achieve this function in Python 2.
Thank you
Just change
from tkinter import simpledialog
from tkinter import *
to
import tkSimpleDialog as simpledialog
from Tkinter import *

Python3 pickle serialization with Cmd

I am new to Python and as my first project I am attempting to convert a Python2 script to Python3.
The script is failing when it attempts to serialize a class using pickle.
It seems as though it is failing as I am trying to save a class which uses the Cmd CLI.
This code works using Python2.
Can anyone tell me what is wrong with the script and how I fix it?
import sys
import cmd
try:
import pickle as pickle
except:
import pickle
import os.path
def main():
app = Labyrinth()
turnfile = "turn0.lwot"
app.Save(turnfile)
class CLI(cmd.Cmd):
def __init__(self):
cmd.Cmd.__init__(self)
class Labyrinth(cmd.Cmd):
def __init__(self):
cmd.Cmd.__init__(self)
def Save(self, fname):
with open(fname, 'wb') as f:
pickle.dump(self,f, 2)
f.close()
print ("Save Successful!")
sys.exit()
if __name__ == '__main__':
main()
Not all objects are picklable. In particular, file objects are problematic because you can't generally restore their state later. cmd.Cmd holds stdin and stdout file objects and that should make them unpicklable. I was quite surprised that it worked in python 2, but it didn't really... Even though the stdin and stdout pickled, the unpickled object you get back later doesn't work, as in this example:
>>> import sys
>>> import pickle
>>> sys.stdout.write('foo\n')
foo
>>> serialized = pickle.dumps(sys.stdout, 2)
>>> stdout = pickle.loads(serialized)
>>> stdout.write('bar\n')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: I/O operation on closed file
>>>
So, even though this bit of code didn't fail, the object shouldn't be usable later. You can add a few special methods to an object that let you fix objects so they can be serialized. Here, I've stripped the bad attributes on save and added them back on restore. Now you can pickle, unpickle and it actually works when you are done.
import sys
import cmd
try:
import cPickle as pickle
except:
import pickle
import os.path
def main():
app = Labyrinth()
turnfile = "turn0.lwot"
app.Save(turnfile)
class CLI(cmd.Cmd):
def __init__(self):
cmd.Cmd.__init__(self)
class Labyrinth(cmd.Cmd):
def __init__(self):
cmd.Cmd.__init__(self)
def Save(self, fname):
with open(fname, 'wb') as f:
pickle.dump(self,f, pickle.HIGHEST_PROTOCOL)
f.close()
print ("Save Successful!")
sys.exit()
def __getstate__(self):
# stdin/out are unpicklable. We'll get new ones on load
return tuple(((k,v) for k,v in self.__dict__.items()
if k not in ('stdin', 'stdout')))
def __setstate__(self, state):
self.__dict__.update(state)
self.stdin = sys.stdin
self.stdout = sys.stdout
if __name__ == '__main__':
main()
Playing with the protocol doesn't help. The full error message (which you should have included) is:
1027:~/mypy$ python3 stack41334887.py
Traceback (most recent call last):
File "stack41334887.py", line 33, in <module>
main()
File "stack41334887.py", line 14, in main
app.Save(turnfile)
File "stack41334887.py", line 27, in Save
pickle.dump(self,f, 3, fix_imports=True)
TypeError: cannot serialize '_io.TextIOWrapper' object
Python3 made some major changes in the io system. This TextIOWrapper is, I think new to Py3.
https://docs.python.org/3.1/library/io.html#io.TextIOWrapper
Can I use multiprocessing.Pool in a method of a class? also had problems serializing a TextIOWrapper.
=========
So inspireed by #tdelaney, I checked the stdin for my PY3 session:
In [1212]: sys.stdin
Out[1212]: <_io.TextIOWrapper name='<stdin>' mode='r' encoding='UTF-8'>
So that's the thing that can't be serialized.

I am trying to play music using tkinter and module mp3 play but it says theres no module named mp3 play(module downloaded)

Although I have downloaded the module mp3play and saved it in python folder.
from Tkinter import *
import mp3play
root = Tk() # create tkinter window
f = mp3play.load('OnOurWay.mp3'); play = lambda: f.play()
button = Button(root, text = 'Play', command = play)
button.pack()
root.mainloop()
I got this error message:
Error:
Traceback (most recent call last):
File "E:/ON F/Tkinter programs/mujic.py", line 2, in <module>
import mp3play
ImportError: No module named mp3play

How to transfer value from one python script class to another python script

I need to connect two python script class to each other and transfer values.
It seems that I made some mistakes to initialize the class objects and passing the
values please note the way I followed and somebody please kindly advise me on where I am getting wrong.
what is wrong with this line of code
def TransferTreeVal(objSubS):
objCM=MainScript.clsMain()
print "Transfer value"
Some more detailed code
##MainScript.py
import os
from Tkinter import *
import Tkinter as tk
import ttk
class clsMain():
def __init__ (objCM):
root['width']=500
root['height']=400
root['bg']='brown'
objCM.MethodDisplay()
def MethodDisplay(objCM):
print "display windows"
root=tk.Tk()
objCM = clsMain()
root.mainloop()
##SubScript.py
import os
from Tkinter import *
import Tkinter as tk
import ttk
import MainScript
class clsSubS():
def __init__ (objSubS):
root['width']=500
root['height']=500
root['bg']='brown'
objSubS.DispWin()
def TransferTreeVal(objSubS):
objCM=MainScript.clsMain()
print "Transfer value"
root=tk.Tk()
objSubS = clsSubS()
The main thing you are doing wrong is that you are importing files that have executable code in them. When you import SubScript.py, it is going to execute the code at the bottom which creates an instance of Tk. However, your main script also creates an instance of Tk and you should only ever have a single instance in a running program.
Normally, if you have a class you want to import, but you also want to use it as a standalone script, you "hide" the standalone script code behind a check like this:
if __name__ == "__main__":
root = tk.Tk()
objSubS = clsSubS()
With that, the code will only get executed if you do python SubScript.py. Also, when you import SubScript, that code will not run.

python importing Tkinter on PC in command line

This is my python program:
from Tkinter import *
root = Tk()
When I do this, it gives me this error message:
Traceback (most recent call last):
File "", line 1, in
File "/usr/lib64/python2.6/lib-tk/Tkinter.py", line 1643, in init
self.tk = _tkinter.create(screenName, baseName, className, interactive, wantobjects, useTk, sync, use)
_tkinter.TclError: no display name and no $DISPLAY environment variable
What do i do?
It's more likely to be like this:
from Tkinter import *
root = Tk()
If you want it in online it should be like this:
from Tkinter import * ;root = Tk()