How to do it...

As our project becomes larger and larger, we naturally break it out into several Python modules. Sometimes it can be a little bit complicated to find modules that are located in different subfolders, either above or below the code that needs to import it.

One practical way to get around this limitation is to use the __init__.py module.

In Eclipse, we can set the Eclipse internal project PyDev PYTHONPATH to certain folders and our Python code will find it. But outside Eclipse, for example, when running from a command window, there is sometimes a mismatch in the Python module import mechanism, and the code will not run.

Here is a screenshot of the empty __init__.py module which appears not with the name __init__ but with the name of the PyDev package it belongs to when opened in the Eclipse code editor. The 1 on the left-hand side of the code editor is the line number and not any code written in this module. There is absolutely no code in this empty __init__.py module:

This file is empty but it does exist:

When we run the following code and click the clickMe button, we get the result shown post the code. This is a regular Python module that does not yet use the __init__.py module code:

The __init__.py module is not the same as the __init__(self): method of a Python class.
# GUI__init.py 
#======================
# imports
#======================
import tkinter as tk
from tkinter import ttk

#======================
# Create instance
#======================
win = tk.Tk()

#======================
# Add a title
#======================
win.title("Python GUI")

#=============================================================
# Adding a LabelFrame and a Button
#=============================================================
lFrame = ttk.LabelFrame(win, text="Python GUI Programming Cookbook")
lFrame.grid(column=0, row=0, sticky='WE', padx=10, pady=10)

def clickMe():
from tkinter import messagebox
messagebox.showinfo('Message Box', 'Hi from same Level.')

button = ttk.Button(lFrame, text="Click Me ", command=clickMe)
button.grid(column=1, row=0, sticky=tk.S)

#======================
# Start GUI
#======================
win.mainloop()

Running the preceding code named GUI__init.py, we get the following output:

In the preceding code, we created the following function, which imports Python's message box and then uses it to display the message box dialog window:

def clickMe(): 
from tkinter import messagebox
messagebox.showinfo('Message Box', 'Hi from same Level.')

When we move the clickMe() message box code into a nested directory folder and try to import it into our GUI module, we might run into some challenges.

We have created three subfolders below where our Python module lives. We have then placed the clickMe() message box code into a new Python module, which we named MessageBox.py. This module lives in Folder3, three levels below where our Python module lives.

We need to import this MessageBox.py module in order to use the clickMe() function that this module contains.

We use Python's relative import syntax:

from Ch11_Code.Folder1.Folder2.Folder3.MessageBox import clickme

The import statement and folder structure can be seen in the following screenshot:

We have deleted the local clickMe() function and now our callback is expected to use the imported clickMe() function. This works from within Eclipse. 
Running the code file GUI__init_import_folder.py with the preceding changes gives the following result:

When we run it from a command prompt, we get an error:

In order to solve this error, we can initialize our Python search path from within the __init__.py module by adding the following code to the__init__.py module:

print('hi from GUI init
') 
from sys import path
from pprint import pprint
#======================================================================
# Required setup for the PYTONPATH in order to find all package folders
#======================================================================
from site import addsitedir
from os import getcwd, chdir, pardir
while True:
curFull = getcwd()
curDir = curFull.split('')[-1]
if 'Ch11_Code' == curDir:
addsitedir(curFull)
addsitedir(curFull + 'Folder1Folder2Folder3')
break
chdir(pardir)
pprint(path)

In the module where we import the clickMe function, we no longer have to specify the full folder path. We can import the module and its function directly:

 
We have to explicitly import __init__ for this code to work.

When we now run our GUI code, we get the same windows as before, but we have removed our dependency on the Eclipse PYTHONPATH variable.

Now, we can successfully run the same code outside the Eclipse PyDev plugin:

Our code has become more Pythonic.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.226.251.206