No module named Tkinter - python

I have a small script in python2.7 that I want to convert into Windows executable. I use pyinstaller for this.
The script:
import sys
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
def get_inputs():
coor = raw_input(">>>top x left: ").replace(" ", "")
top, left = coor.split("x")
top = int(top.strip())
left = int(left.strip())
return top, left
def plot_location(top, left):
img= mpimg.imread('nbahalfcourt.jpg')
plt.imshow(img)
plt.scatter(left, top)
plt.grid()
plt.show()
def main():
top, left = get_inputs()
plot_location(top, left)
if __name__ == '__main__':
print "Input top x left coordinates (no space) eg: 44x232"
run = True
while run:
main()
Basically, the script just plots a point on a grid.
The converting process finishes successfully. When I run the .exe however I've got the ImportError (see below) even though I have no reference to Tkinter anywhere.
What could went wrong here?

I have a feeling that matplotlib uses the Tkinter module internally, but imports it in a non-standard way. Then pyinstaller doesn't notice Tkinter is needed, and subsequently doesn't bundle it into the executable.
Try explicitly putting import Tkinter at the top of your script.

I had the same issue and none of the solutions here worked. I was using Pyinstaller 3.2 (the latest version at the time) and everything was fixed (and no import statements needed) when I upgraded to the latest developer version using
pip install https://github.com/pyinstaller/pyinstaller/archive/develop.zip
This seems to indicate that at the times of writing this that all the kinks to this issue are still being worked out
EDIT: As of January 15 2017 Pyinstaller version 3.2.1 was released. I now use this and it solves this issue along with others like this and this that I could previously only solve by using the developer version. So I highly recommend upgrading to the latest version if you haven't already.

Related

"CreateDC failed, Screen size info may be incorrect"

I am trying to use OpenGL with python. I have Pyton 3.7.4, on a Windows 10 machine.
I downloaded PyOpenGL and PyOpenGL_accelerate from .whl files, and I have downloaded the freeglut.dll file separately and placed it in the same directory as the script I am running.
My initial scripts is just:
import OpenGL
from OpenGL.GL import *
from OpenGL.GLUT import *
from OpenGL.GLU import *
glutInit()
which gives the following error message:
freeglut (foo): fgPlatformInitialize: CreateDC failed, Screen size
info may be i ncorrect This is quite likely caused by a bad '-display'
parameter
(Without the freeglut.dll file, it gives a NameError complaint about glutInit() being undefined).
I have seen error on this question but a) they were doing it with C/C++ and b) the answer did not say where one had to make the change.
Any ideas on what I am supposed to do?
UPDATE
The problem may be this:
import os
os.getenv('DISPLAY')
# 'needs-to-be-defined'
What should I call this environment variable?
I just added this piece of code at the beginning of my script and it worked:
import os
try:
del os.environ['DISPLAY']
except:
pass
Ideally I would delete the DISPLAY environment variable for all processes but I did not manage.
glutInit(["-display","0"]) - as an idea based on :
https://www.opengl.org/resources/libraries/glut/spec3/node10.html

Is there a way to automatically switch matplotlib backend in Jupyter?

When working with my python package, a certain function has some interactive matplotlib stuff going on.
In Jupyter Notebook I always have to use the magic %matplotlib qt to switch backend in order to make it work.
However, this might seem obvious to me, but others who're trying to work with my package this is not that straight forward.
This is what I have so far in my __init__.py:
def run_from_notebook():
return hasattr(__builtins__, '__IPYTHON__')
if run_from_notebook():
# this has no effect
try:
from IPython import get_ipython
ipython = get_ipython()
except ImportError:
import IPython.ipapi
ipython = IPython.ipapi.get()
ipython.magic("matplotlib qt")
I also tried:
if matplotlib.get_backend() != 'Qt5Agg':
matplotlib.use('Qt5Agg')
but still no effect.
Is there a way to automatically switch backend in Jupyter Notebook when someone imports my package?
and also: Is there any reason it's not considered as a good practice?
It turns out that the problem is with the run_from_notebook function. When running it simply in a notebook cell it returns True, but when it's imported from my module, it returns False. The question now is rather: How to detect if code is run inside Jupyter?
For example running manually
def switch_backend_to_Qt5():
import matplotlib
if matplotlib.get_backend() != 'Qt5Agg':
matplotlib.use('Qt5Agg')
gets the job done.
EDIT :
The following function suits my needs:
import os
def run_from_notebook():
try:
__IPYTHON__
# If it's run inside Spyder we don't need to do anything
if any('SPYDER' in name for name in os.environ):
return False
# else it's probably necessary to switch backend
return True
except NameError:
return False

Why do imports work only when running without run configuration?

In PyCharm, I have one common module (called common.py) that I want to import from a few other files. It used to be working fine, until recently when I ran the program using Ctrl+Enter. Since then, I can now only run the code with Ctrl+Enter, using the normal run configuration doesn't recognize the imports; it says "unused import" and doesn't resolve references to methods in common.py. Here is the code in the file I'm trying to run:
from matplotlib import pyplot as plt
from matplotlib import colors as cl
from common import *
N = np.arange(5, 30, 1, int)
get_noiseless_eigenvalues(np.matrix([[1]]))
Both np and get_noiseless_eigenvalues aren't resolved by PyCharm, even though they are both present in common.py:
import numpy as np
def get_noiseless_eigenvalues(m: np.matrix):
return [v for v in np.linalg.eigh(m)[1] if sum(v) == 0]
I checked that the directory is indeed still marked as Sources Root. What could be the problem here?
Edit: I checked the changes with git, turns out that an empty __init__.py was added in two locations; for now, I can at least run the program normally but I'm still wondering why this happened

How to disable welcome message when importing pygame

When I import pygame, it prints the version and welcome message. The message reads:
pygame 1.9.4
Hello from the pygame community. https://www.pygame.org/contribute.html
Why is this printed?
How can I disable this message?
As can be seen in the source code, the message is not printed if the environment variable PYGAME_HIDE_SUPPORT_PROMPT is set. So the following code could be used to import pygame without printing the message:
import os
os.environ['PYGAME_HIDE_SUPPORT_PROMPT'] = "hide"
import pygame
Note that the value does not have to be "hide" but can be anything else as well, and the environment variable can also be set in other ways to achieve the same.
Here's the better way alternative suggested by #Mad Physicist:
import contextlib
with contextlib.redirect_stdout(None):
import pygame
Or, if your Python is older than 3.4 you can achieve the same thing without the contextlib import by temporarily disabling stdout while importing pygame.
import os, sys
with open(os.devnull, 'w') as f:
# disable stdout
oldstdout = sys.stdout
sys.stdout = f
import pygame
# enable stdout
sys.stdout = oldstdout
The source code contains a condition guarding the printing of this message:
if 'PYGAME_HIDE_SUPPORT_PROMPT' not in os.environ:
print('pygame %s' % ver)
print('Hello from the pygame community. https://www.pygame.org/contribute.html')
See this commit
This was added fairly recently (October 2018) and so far 1.9.4 was released prior to this. Once the next version > 1.9.4 is released you should simply by able to run your code with PYGAME_HIDE_SUPPORT_PROMPT= ./my_code.py to hide the message.
You can navigate to the pygame library folder, something like this for 3.6 32 bit version:
Python36-32\Lib\site-packages\pygame
and edit the __init__.py file and remove the last line to get rid of this message.
import pygame
Get the location of the init file: f = pygame.__file__
Open f and comment out the print on the last two lines of the file
About Eduardo's answer, I was having problems with my formatter autopep8 and was unable to put the line to set the PYGAME_HIDE_SUPPORT_PROMPT environment variable above the line to import pygame. Thus, I had to do something like this:
import os # last import (all other imports above this one)
os.environ['PYGAME_HIDE_SUPPORT_PROMPT'] = 'hide'
def import_pygame():
global pygame
import pygame
import_pygame()
I hope this helps anyone having the same issue.
For me, only this worked in python 3:
import sys, os
# Disable print
def blockPrint():
sys.stdout = open(os.devnull, 'w')
# Enable print
def enablePrint():
sys.stdout = sys.__stdout__
blockPrint()
import pygame
enablePrint()
(thanks for Brigand!)
This works fine for me:
from os import environ
environ['PYGAME_HIDE_SUPPORT_PROMPT'] = '1'
import pygame
You just have to make sure your imports don't get rearranged.
And it has come before any import of anything that imports pygame, not just before your import of pygame.
For me, PYGAME_HIDE_SUPPORT_PROMPT does not work.
Add this for the whole block of imports:
sys.stdout = open(os.devnull, "w")
# your other imports go here
import pygame
sys.stdout = sys.__stdout__
I kindly ask you though to only use this if the program will be launched graphically, to avoid spawning a console, or when you'll leave another message. You can print a shorter or more fitting one, or you can add it in a GUI.
Editing Pygame is not desirable if you are going to distribute your project in any way.
Go in pygame's __init__.py file, go at the bottom of that file, and comment out those two print function-
print('pygame %s' % ver)
print('Hello from the pygame community. https://www.pygame.org/contribute.html')
However, I would not do that since, pygame community is an open-source community, and they would want as many people as possible, to contribute to pygame, thats why they have this print function at that last. I would not comment it out, if I were you.
This is one time process to disable it!
Step 1:
Run a dummy.py containing following code:
import pygame
pygame.__file__
Step 2:
Copy the path of the pygame source code excluding __init__.py
Example:
C:\\Users\\dell\\AppData\\Roaming\\Python\\Python37\\site-packages\\pygame\\
Step 3:
Go to the copied location by pasting it into the run dialog box or any other way
Step 4:
open __init__.py in any text editor and search for welcome
delete the following code from the file:
if 'PYGAME_HIDE_SUPPORT_PROMPT' not in os.environ:
print('pygame %s' % ver)
print('Hello from the pygame community. https://www.pygame.org/contribute.html')
Now save the file and you are good to go!
You can go into pygame's __init__.py file and comment out the line that causes the message to be printed. It's exactly at line 355. Here is the code that does that.
# Thanks for supporting pygame. Without support now, there won't be pygame
#later.
if 'PYGAME_HIDE_SUPPORT_PROMPT' not in os.environ:
print('pygame {} (SDL {}.{}.{}, Python {}.{}.{})'.format(
ver, *get_sdl_version() + sys.version_info[0:3]
))
print('Hello from the pygame community.
https://www.pygame.org/contribute.html')
You can just go ahead and comment those lines out. I have tested it, it does not cause any problems.
But always be thankful for pygame's free and opensource library.
# remove pygame installed with "pip install..."
python pip uninstall pygame
# remove all folder with pygame
sudo apt-get update -y; sudo apt-get upgrade -y
sudo apt-get install python-pygame
The version installed with the last line will work without announcing its name.

Signal handler works in python but not in ipython

I'm attempting to set the numpy print options using a signal handler on the window resize event. Don't want to make the connection until numpy has been imported, and don't want to import numpy automatically at python startup. I've got it almost-working with the code below:
# example.py
import wrapt
#wrapt.when_imported('numpy')
def post_import_hook(numpy):
import signal
try:
from shutil import get_terminal_size
except ImportError:
# Python 2
from shutil_backports import get_terminal_size
def resize_handler(signum=signal.SIGWINCH, frame=None):
w, h = get_terminal_size()
numpy.set_printoptions(linewidth=w)
print('handled window resize {}'.format(w))
resize_handler()
signal.signal(signal.SIGWINCH, resize_handler)
It works in vanilla python REPL (test with python -i example.py and resize the terminal a bit). But it doesn't work in ipython when the same code is added to my startup ipython config, and I don't understand why.
I'm not fixed on this particular approach (that's just what I've tried so far), so I'll phrase the question more generally:
How can numpy correctly fill to the terminal width automatically in ipython?
You can use print(np.arange(200)), for example, to check numpy's line wrapping behaviour.
Inspired by the standard fix for printing large arrays without truncation, I tried setting the line width to infinity. This seems to be working fine both in the REPL and in ipython, so I suggest this workaround:
import numpy
numpy.set_printoptions(linewidth=numpy.inf)
This doesn't explain why your fix doesn't work for ipython, but in case the above line doesn't mess with anything unexpected, it should make printing immune to resizing.

Categories