Making .exe from the Python Script that uses GIS libraries such as geopandas, folium - python-3.x

It's a very straightforward and broad question I know but I have very little time so I have to ask. I created an interface to do some GIS calculations and for that I used below libraries in backend.
import osmnx as ox, networkx as nx, geopandas as gpd, pandas as pd
from shapely.geometry import LineString, Point
from fiona.crs import from_epsg
import branca.colormap as cm
import folium
from folium.plugins import MarkerCluster
import pysal as ps
and these for frontend
import tkinter as tk
from tkinter import ttk
from tkinter.filedialog import askopenfilename, asksaveasfilename,
askdirectory
import backend as bk
I'm trying to make it an executable program and I've tried PyInstaller but it did not work because of the dependencies. Is there any way to do it with PyInstaller? or any other libraries? Or what should I do?
p.s : I'm using python 3.6
2nd EDIT:
I tried cx_freeze and created a setup.py and build it. After that, when I double click on the program It simply does nothing. No error messages, anything. My code is in below:
import cx_Freeze
import sys
import os
PYTHON_INSTALL_DIR = os.path.dirname(sys.executable)
os.environ['TCL_LIBRARY'] = os.path.join(PYTHON_INSTALL_DIR, 'tcl', 'tcl8.6')
os.environ['TK_LIBRARY'] = os.path.join(PYTHON_INSTALL_DIR, 'tcl', 'tk8.6')
include_files = [(os.path.join(PYTHON_INSTALL_DIR, 'DLLs', 'tk86t.dll'), os.path.join('lib', 'tk86t.dll')),
(os.path.join(PYTHON_INSTALL_DIR, 'DLLs', 'tcl86t.dll'), os.path.join('lib', 'tcl86t.dll'))]
packages = ["pandas", "numpy", "tkinter", "matplotlib", "osmnx", "networkx",
"geopandas", "shapely", "fiona", "branca", "folium",
"pysal"]
base = None
if sys.platform == "win32":
base = "Win32GUI"
executables = [cx_Freeze.Executable("frontend.py", base=base, icon="transport.ico")]
cx_Freeze.setup(
name = "Network_Analyst",
options = {"build_exe": {"packages":packages,
"include_files":include_files}},
version = "0.01",
description = "Network analyst",
executables = executables
)
My program consists of two scripts which are frontend and backend. I'm importing backend on the frontend section, should I add it somewhere in the setup code? And one more thing, I'm working on an environment to do these processes, Is this has an effect on building a setup?
I'm giving a sample from my code to make your understanding better:
In frontend part I'm calling backend as
import backend as bk
and in the script:
class Centrality(tk.Frame):
def degree_cent(self):
print("Calculating Degree Centrality")
G = self.findG()
try:
bk.degree_cent(G, self.t3.get("1.0",'end-1c'), self.t2.get("1.0",'end-1c'))
except:
bk.degree_cent(G, self.t3.get("1.0",'end-1c'))
In backend I don't use OOP, I just write the functions such as:
import osmnx as ox, networkx as nx, geopandas as gpd, pandas as pd
def degree_cent(G, outpath, *args):
G_proj = ox.project_graph(G)
nodes, edges = ox.graph_to_gdfs(G_proj)
nodes["x"] = nodes["x"].astype(float)
degree_centrality = nx.degree_centrality(G_proj)
degree = gpd.GeoDataFrame(pd.Series(degree_centrality), columns=["degree"])
Executable program still doesn't respond when I'm clicking on it. No respond at all. No any windows event (I've checked it from Windows Event Viewer).

As far as another library is concerned: you can use cx_Freeze to make an executable out of your Python program.
You can install cx_Freeze by issuing the command
python -m pip install cx_Freeze --upgrade
in a terminal or command prompt. You'll find links to the cx_Freeze documentation and source code on the cx_Freeze entry page.
To create an executable, you need to create a setup script setup.py for your application an then issue the command
python setup.py build
You can find a working example using tkinterin this question
tkinter program compiles with cx_Freeze but program will not launch
and its accepted answer. It also contains useful links.
In order to use pandas in your main script, you'll need to modify the setup.py script of the example linked above by adding
packages = ['numpy']
and replacing the options argument in the setup call by
options={'build_exe': {'include_files': include_files, 'packages': packages}}
You also might need further tweaking for the other modules you are using (geopandas, folium, ...). If it does not work with the example described above, please edit your question and add the setup.py script you are using and the error message reported to get further help.
EDIT:
For cx_Freeze version 5.1.1, the TCL/TK DLLs need to be included in a lib subdirectory of the build directory. You can do that by passing a tuple (source, destination) to the corresponding entry of the include_files list option:
include_files = [(os.path.join(PYTHON_INSTALL_DIR, 'DLLs', 'tk86t.dll'), os.path.join('lib', 'tk86t.dll')),
(os.path.join(PYTHON_INSTALL_DIR, 'DLLs', 'tcl86t.dll'), os.path.join('lib', 'tcl86t.dll'))]
As far as the backend is concerned, if you use import backend in frontend.py, it should be no problem, cx_Freeze should freeze it correctly.

Related

Python to EXE - PySide2 and Custom Modules

I'm trying to create an EXE from a Python project I built and I'm running into some issues. I've done this before with PyInstaller for simpler tools and cx-freeze for tools where I use custom modules but the way I used to set it up doesn't seem to be working anymore.
In this particular case I've tried:
cx-freeze==6.10
pyinstaller==4.10
py2exe==0.11.1.0
auto-py-to-exe==2.18.0
and a few others with no luck
Everything works perfectly fine through the Python 3.8 interpreter. I'm assuming it's either because of the way I'm importing PySide2 here (which I don't normally do but did for this project to see if it would speed up my programming time) or that the EXE modules can't find my custom modules. Here is a mock version of my program (names/paths changed for simplicity):
Example folder of my project ("C:\a\MyProjects\Project1"):
Example folder of the custom module I'm using. Each using various other built-in and/or 3rd party python modules. ("C:\a\path\to\external\modules"):
Example of my main file (C:\a\MyProjects\Project1\ui.py) I want to turn into an EXE:
import os
import sys
import colorsys
from PySide2.QtWidgets import *
from PySide2.QtCore import *
from PySide2.QtGui import *
import utils # module in project ("C:\a\MyProjects\Project1\utils.py")
sys.path.append(r"C:\a\path\to\external\modules") # custom module location for MyModule
from MyModule.foo import module1 as foo_mod1
from MyModule.foo import module2 as foo_mod2
from MyModule.bar import module1 as bar_mod1
from MyModule.bar import module2 as bar_mod2
from MyModule.baz import module1 as baz_mod1
from MyModule.baz import module2 as baz_mod2
class MainDialog(QDialog):
[...code...]
[...use of "dark.stylesheet"...]
[...use of "images\image 1.png"...]
[...use of "images\image 2.png"...]
def main():
global win
try: # try to close existing instances
win.close()
except NameError:
pass
win = MainDialog()
win.show()
if __name__ == "__main__":
app = QApplication.instance()
if not app:
app = QApplication(sys.argv)
main()
sys.exit(app.exec_())
Can someone tell me the best module and method to make this into a windowed (console-less), if possible, single file application. This is one of the more complicated tools I've had to make into a desktop app so if I can figure this out I should be good for most of the other things I have to do.
Thanks in advance.
EDIT:
Example of cx-freeze setup.py file in project I tried (C:\a\MyProjects\Project1\setup.py):
from cx_Freeze import setup, Executable
import sys
setup(
name="MyProject",
version="1.0",
options={'build_exe': {
'excludes': ["Tkinter"],
'includes': ["utils", "MyModule.foo", "MyModule.bar", "MyModule.baz"],
'path': sys.path + [r"C:\a\path\to\external\modules"],
'include_files': ["images\image 1.png", "images\image 2.png"],
'packages': ["PySide2.QtWidgets", "PySide2.QtCore", "PySide2.QtGui"]}},
executables=[Executable("ui.py", base="Win32GUI")]
Example of pyinstaller cmd command I tried:
cd C:\\a\MyProjects\Project1
pyinstaller -p "C:\a\path\to\external\modules" --onefile -w ui.py
# even tried this with a custom spec file like:
# pyinstaller --onefile -w ui.spec
There is a command in PyInstaller to include hidden modules call --hidden-module (You can use multile times). So, you can just do
pyinstaller -p "C:\a\path\to\external\modules" --onefile -w --hidden-module="example module 1" -hidden-module="example module 2" ui.py
This seems to have fixed itself after I got a new workstation and installed the latest Python (3.10) and Pyinstaller (5.1) versions.
Also think having your custom Python Libraries in the PYTHONPATH and/or PATH Environment variables may be important for allowing Pyinstaller to find them.

Create executable with python 3.7 PyQt5 and cx_Freeze but DLL Failed to load

I developed a "not so simple" GUI with PyQt5 via Anaconda 3 (Python 3.7) and Designer.
I have 3 different .ui files that I import in my program.
When I run cx_Freeze, everything runs good, I create the .exe. Then, I copy the "platform" folder from my "Python" folder in the "Build" folder that cx_Freeze creates.
BUT, when I pass it to an other machine without anything on it (no anaconda, no python, no cx_Freeze, nothing), the app doesn't run. I get:
ImportError: DLL load failed: The specified module could not be found
It happens in the 10th line of my code which is:
from PyQt5 import QtGui, QtWidgets
The imports in my code are:
from PyQt5 import QtGui, QtWidgets
import sys
import glob
import datetime
from matplotlib.backends.qt_compat import QtCore, QtWidgets
from matplotlib.backends.backend_qt5agg import FigureCanvas
from matplotlib.figure import Figure
import numpy as np
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import design
import flex
import entry
design, flex and entry are the .ui files. They all contain this part at the end (don't know if it helps):
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
Dialog = QtWidgets.QDialog()
ui = Ui_Dialog()
ui.setupUi(Dialog)
Dialog.show()
sys.exit(app.exec_())
And finally, the setup file I run with cx_Freeze:
import sys
from cx_Freeze import setup, Executable
import matplotlib
import numpy
# Dependencies are automatically detected, but it might need fine tuning.
build_exe_options = {"packages": ["os", "matplotlib"], "includes": ["PyQt5", "atexit"], "excludes": ["tkinter"]}
# GUI applications require a different base on Windows (the default is for a
# console application).
base = None
if sys.platform == "win32":
base = "Win32GUI"
setup( name = "Flexicounts",
version = "0.1",
description = "Flexicounts pour faire tes comptes facilement",
options = {"build_exe": build_exe_options},
executables = [Executable("flexicounts.py", base=base)])
I read a lot about it, but I feel that there is no "miracle" solution...
Could you help me freeze my app and make it run on a "virgin machine" ?
You might be facing Issue #504 of the cx_Freeze repository. In that case, quoting a comment by marceloduarte there:
The workaround is to copy python3.dll to the directory where the executable was made. cx_Freeze copies python37.dll, but does not copy python3.dll. The vcruntime140.dll may also have to be copied when it no longer exists on the system.
First try to manually copy these DLLs (you find them in the directory of your python installation containing python.exe) to the directory of your executable. If that solves the problem, you can tell cx_Freeze to do it for you by using the include_files list of the build_exe_options. Modify you setup script as follows:
import os
python_dir = os.path.dirname(sys.executable) # directory of your python installation
build_exe_options = {"packages": ["os", "matplotlib"],
"includes": ["PyQt5", "atexit"],
"include_files": [os.path.join(python_dir, "python3.dll"), os.path.join(python_dir, "vcruntime140.dll")],
"excludes": ["tkinter"]}
Maybe you need to copy further DLLs, such as msvcp140.dll, or any other DLL present inside the site-packages/PyQt5 directory (including subdirectories) of your Python installation.
I faced a similar problem recently, with the following versions:
python 3.6.6 x64
cx-Freeze==6.10
PyQt5==5.15.4
PyQt5-Qt5==5.15.2
PyQt5-sip==12.9.0
PyQt5-stubs==5.15.2.0
PyQtWebEngine==5.15.5
PyQtWebEngine-Qt5==5.15.2
Symptoms :
The cx_Freeze package was successful and execution working fine on my machine, because (as I found later and explained below) I had Python 3.6 x64 installed on my machine and visibile via environement variables.
On an another machine, the package failed with the exact same error on first PyQt5 import:
ImportError: DLL load failed: The specified module could not be found
However, in my case, all the necessary dlls seemed all in the right place :
cx_Freeze seemed to have correctly put python3.dll and python36.dll next to the executable. But no other dll were copied there (no vcruntime140.dll for instance)
all the necessary python modules were in place, including PyQt5 and all its dlls
Solution that was working :
(I created a cx_Freeze issue)
Contrary to the other answer, I had to copy
python3.dll
(either from <cx_freeze_build_dir_target> or from python3.6.6 install dir ...)
(python36.dll works too but is much bigger)
into the following folders:
<cx_freeze_build_dir_target>/lib/PyQt5/
The corresponding cx_Freeze setup config for this would be to add this to the include_files list, in the following fashion.
Unfortunatly, this does not work due to cx_Freeze having an sort of exception file liste that includes python3.dll and prevents the actual copy via include_files. So, the copy should be performed manually, after full setup script execution...
# import pkgutil
from pathlib import Path
from glob import glob
import sys
# ... your stuff
#
includes_list = []
# your stuff
# ...
# pyqt5 force copy of pythonlib(s) into qt5 target dir
# may not work if you intend to zip pyqt5 ?
python_dir = Path(sys.executable).parent
python_dlls = [ Path(p) for p in glob(f"{python_dir.as_posix()}/python*.dll")]
pyqt_base_dir = Path("lib", "PyQt5")
# prepare cx_Freeze tuples (source file, target dir)
includes_list+= [ (p, pyqt_base_dir / p.name) for p in python_dlls ]
build_exe_options = {"packages" : ..., # your packages
"includes" : ..., # yours
"include_files": includes_list,
"excludes" : ... # yours
}

Add numpy.get_include() argument to setuptools without preinstalled numpy

I am currently developing a python package that uses cython and numpy and I want the package to be installable using the pip install command from a clean python installation. All dependencies should be installed automatically. I am using setuptools with the following setup.py:
import setuptools
my_c_lib_ext = setuptools.Extension(
name="my_c_lib",
sources=["my_c_lib/some_file.pyx"]
)
setuptools.setup(
name="my_lib",
version="0.0.1",
author="Me",
author_email="me#myself.com",
description="Some python library",
packages=["my_lib"],
ext_modules=[my_c_lib_ext],
setup_requires=["cython >= 0.29"],
install_requires=["numpy >= 1.15"],
classifiers=[
"Programming Language :: Python :: 3",
"Operating System :: OS Independent"
]
)
This has worked great so far. The pip install command downloads cython for the build and is able to build my package and install it together with numpy.
Now I want to improve the performance of my cython code, which leads to some changes in my setup.py. I need to add include_dirs=[numpy.get_include()] to either the call of setuptools.Extension(...) or setuptools.setup(...) which means that I also need to import numpy. (See http://docs.cython.org/en/latest/src/tutorial/numpy.html and Make distutils look for numpy header files in the correct place for rationals.)
This is bad. Now the user cannot call pip install from a clean environment, because import numpy will fail. The user needs to pip install numpy before installing my library. Even if I move "numpy >= 1.15" from install_requires to setup_requires the installation fails, because the import numpy is evaluated earlier.
Is there a way to evaluate the include_dirs at a later point of the installation, for example, after the dependencies from setup_requires or install_requires have been resolved? I really like to have all dependencies resolved automatically and I dont want the user to type multiple pip install commands.
The following snippet works, but it is not officially supported because it uses an undocumented (and private) method:
class NumpyExtension(setuptools.Extension):
# setuptools calls this function after installing dependencies
def _convert_pyx_sources_to_lang(self):
import numpy
self.include_dirs.append(numpy.get_include())
super()._convert_pyx_sources_to_lang()
my_c_lib_ext = NumpyExtension(
name="my_c_lib",
sources=["my_c_lib/some_file.pyx"]
)
The article How to Bootstrap numpy installation in setup.py proposes using a cmdclass with custom build_ext class. Unfortunately, this breaks the build of the cython extension because cython also customizes build_ext.
First question, when is numpy needed? It is needed during the setup (i.e. when build_ext-funcionality is called) and in the installation, when the module is used. That means numpy should be in setup_requires and in install_requires.
There are following alternatives to solve the issue for the setup:
using PEP 517/518 (which is more straight forward IMO)
using setup_requires-argument of setup and postponing import of numpy until setup's requirements are satisfied (which is not the case at the start of setup.py's execution)
PEP 517/518-solution:
Put next to setup.py a pyproject.toml-file , with the following content:
[build-system]
requires = ["setuptools", "wheel", "Cython>=0.29", "numpy >= 1.15"]
which defines packages needed for building, and then install using pip install . in the folder with setup.py. A disadvantage of this method is that python setup.py install no longer works, as it is pip that reads pyproject.toml. However, I would use this approach whenever possible.
Postponing import
This approach is more complicated and somewhat hacky, but works also without pip.
First, let's take a look at unsuccessful tries so far:
pybind11-trick
#chrisb's "pybind11"-trick, which can be found here: With help of an indirection, one delays the call to import numpy until numpy is present during the setup-phase, i.e.:
class get_numpy_include(object):
def __str__(self):
import numpy
return numpy.get_include()
...
my_c_lib_ext = setuptools.Extension(
...
include_dirs=[get_numpy_include()]
)
Clever! The problem: it doesn't work with the Cython-compiler: somewhere down the line, Cython passes the get_numpy_include-object to os.path.join(...,...) which checks whether the argument is really a string, which it obviously isn't.
This could be fixed by inheriting from str, but the above shows the dangers of the approach in the long run - it doesn't use the designed mechanics, is brittle and may easily fail in the future.
the classical build_ext-solution
Which looks as following:
...
from setuptools.command.build_ext import build_ext as _build_ext
class build_ext(_build_ext):
def finalize_options(self):
_build_ext.finalize_options(self)
# Prevent numpy from thinking it is still in its setup process:
__builtins__.__NUMPY_SETUP__ = False
import numpy
self.include_dirs.append(numpy.get_include())
setupttools.setup(
...
cmdclass={'build_ext':build_ext},
...
)
Yet also this solution doesn't work with cython-extensions, because pyx-files don't get recognized.
The real question is, how did pyx-files get recognized in the first place? The answer is this part of setuptools.command.build_ext:
...
try:
# Attempt to use Cython for building extensions, if available
from Cython.Distutils.build_ext import build_ext as _build_ext
# Additionally, assert that the compiler module will load
# also. Ref #1229.
__import__('Cython.Compiler.Main')
except ImportError:
_build_ext = _du_build_ext
...
That means setuptools tries to use the Cython's build_ext if possible, and because the import of the module is delayed until build_ext is called, it founds Cython present.
The situation is different when setuptools.command.build_ext is imported at the beginning of the setup.py - the Cython isn't yet present and a fall back without cython-functionality is used.
mixing up pybind11-trick and classical solution
So let's add an indirection, so we don't have to import setuptools.command.build_ext directly at the beginning of setup.py:
....
# factory function
def my_build_ext(pars):
# import delayed:
from setuptools.command.build_ext import build_ext as _build_ext#
# include_dirs adjusted:
class build_ext(_build_ext):
def finalize_options(self):
_build_ext.finalize_options(self)
# Prevent numpy from thinking it is still in its setup process:
__builtins__.__NUMPY_SETUP__ = False
import numpy
self.include_dirs.append(numpy.get_include())
#object returned:
return build_ext(pars)
...
setuptools.setup(
...
cmdclass={'build_ext' : my_build_ext},
...
)
One (hacky) suggestion would be using the fact that extension.include_dirs is first requested in build_ext, which is called after the setup dependencies are downloaded.
class MyExt(setuptools.Extension):
def __init__(self, *args, **kwargs):
self.__include_dirs = []
super().__init__(*args, **kwargs)
#property
def include_dirs(self):
import numpy
return self.__include_dirs + [numpy.get_include()]
#include_dirs.setter
def include_dirs(self, dirs):
self.__include_dirs = dirs
my_c_lib_ext = MyExt(
name="my_c_lib",
sources=["my_c_lib/some_file.pyx"]
)
setup(
...,
setup_requires=['cython', 'numpy'],
)
Update
Another (less, but I guess still pretty hacky) solution would be overriding build instead of build_ext, since we know that build_ext is a subcommand of build and will always be invoked by build on installation. This way, we don't have to touch build_ext and leave it to Cython. This will also work when invoking build_ext directly (e.g., via python setup.py build_ext to rebuild the extensions inplace while developing) because build_ext ensures all options of build are initialized, and by coincidence, Command.set_undefined_options first ensures the command has finalized (I know, distutils is a mess).
Of course, now we're misusing build - it runs code that belongs to build_ext finalization. However, I'd still probably go with this solution rather than with the first one, ensuring the relevant piece of code is properly documented.
import setuptools
from distutils.command.build import build as build_orig
class build(build_orig):
def finalize_options(self):
super().finalize_options()
# I stole this line from ead's answer:
__builtins__.__NUMPY_SETUP__ = False
import numpy
# or just modify my_c_lib_ext directly here, ext_modules should contain a reference anyway
extension = next(m for m in self.distribution.ext_modules if m == my_c_lib_ext)
extension.include_dirs.append(numpy.get_include())
my_c_lib_ext = setuptools.Extension(
name="my_c_lib",
sources=["my_c_lib/some_file.pyx"]
)
setuptools.setup(
...,
ext_modules=[my_c_lib_ext],
cmdclass={'build': build},
...
)
I found a very easy solution in this post:
Or you can stick to https://github.com/pypa/pip/issues/5761. Here you install cython and numpy using setuptools.dist before actual setup:
from setuptools import dist
dist.Distribution().fetch_build_eggs(['Cython>=0.15.1', 'numpy>=1.10'])
Works well for me!

Comand promp closes instantly with cx_Freeze and requests module

Im trying to build a simple executable file from python using cx_Freeze, but the script uses request module. As many many other threads say, it seems to be a problem involving cx_freeze and requests module, something about the path of the files that requests need to run and cx_freeze changes or doesnt import when freezing.
The build process works just fine, but when the exe is created, if i try to open it, a comand promp shows for a fraction of a second and then closes, displaying something so quickly that i dont have time to read or even snapshot, but it doesnt have the structure of an error message.
I think the problem is probably the thing about paths, but i dont know how to solve it, and everything i've found in internet haven't worked for me.
Please help.
Here is a copy of the test file named "prueba2.py"
import requests
print("hi")
print(requests)
input()
and the setup.py
from cx_Freeze import setup, Executable
import sys
import os
import requests.certs
base = None
executables = [Executable("prueba2.py", base=base)]
packages = ["idna"]
options = {
'build_exe': {
'packages': packages,
'include_files': [os.path.join(sys.base_prefix, 'DLLs','sqlite3.dll'),
(requests.certs.where(), 'cacert.pem')]
},
}
setup(
name="<any name>",
options=options,
requires=["requests"],
version="<any number>",
description='<any description>',
executables=executables
)
It seems there are some dependencies for cx_freeze in new versions of the module
try modifying the main file like this:
import requests
from multiprocessing import Queue
print("hi")
print(requests)
input()
and setup.py as :
from cx_Freeze import setup, Executable
import sys
import os
import requests.certs
base = None
executables = [Executable("prueba2.py", base=base)]
packages = ["idna"]
options = {
'build_exe': {
'packages': packages,
'include_files': [os.path.join(sys.base_prefix, 'DLLs', 'sqlite3.dll'),
(requests.certs.where(), 'cacert.pem')]
},
}
setup(
name="name",
options=options,
requires=["requests"],
version="1",
description='test',
executables=executables
)

import hashlib - cxFreeze

I wrote a programm which uses cxFreeze but if I try to compile it with cxFreeze I get the error:
Missing modules:
? _md5 imported from hashlib
? _sha1 imported from hashlib
? _sha256 imported from hashlib
? _sha512 imported from hashlib
It seems to me, that cxFreeze is not compatible with the hashlib module because the error is easy to reproduce. You just have to import hashlib and try to compile it.
Example:
cx_test.py:
import hashlib
setup.py (for cxFreeze):
import sys
from cx_Freeze import setup, Executable
buildOptions = dict(
compressed = True,
path = sys.path)
setup(
name = "Hashlibtest",
options = dict(build_exe = buildOptions),
includes = ["hashlib"],
executables = [Executable("cx_test.py")]
)
Any ideas how I can fix the problem?
I work with Python3.2 under Ubuntu 12.04
It's not a problem - if you look at the source code for hashdist, it uses different modules depending on whether or not Python was compiled with OpenSSL. Other modules might import one thing on Windows and another on Linux, or one for Python 2 and another for Python 3.
In all these cases, cx_Freeze sees all the import x statements, and looks for all of the modules. If it can't find one, it gives you that message. But it will still produce a program, and that will normally still work, unless there are other problems.
I've seen those messages for hashlib before, and the resulting program has worked just fine.

Resources