How to package a Python module - python

I am a newbie to Python and I have been going through the exercises in LPTHW:
http://learnpythonthehardway.org/book/ex46.html
The explanation of packaging the author gave was very vague, so I did some researching, but I was still left with some questions in the end.
Firstly, what happens if you have a module that imports another module? Do you put the module that is imported into a subdirectory of the directory containing the first module, or in another separate directory in the root?
Secondly, once you have installed the entire package how do you run any scripts that are in the bin folder?

Firstly, what happens if you have a module that imports another
module? Do you put the module that is imported into a subdirectory of
the directory containing the first module, or in another separate
directory in the root?
A module is just a file with Python code - you don't need to put it in a separate directory. The easiest option is to put the file in the same directory that contains the module that will be doing the import.
If you put it in some other directory and that directory is not a package you will not be able to import it at all (unless you manually mess around with PYTHONPATH which you shouldn't).
Secondly, once you have installed the entire package how do you run
any scripts that are in the bin folder?
The way to do this is to specify the scripts for your application in the setup.py file using console_scripts. This way, when your package is installed, your scripts will be built correctly and placed in the right directories on the target platform so that you can directly execute them (without being aware of their location on the filesystem).
As an example, you can browse the setup.py file for the django project.
If you are installing a package, you don't need to know where the actual script is located - simply install the package and execute the command directly from your prompt.

Related

How to import a file from the folder that my .py script is being called from?

I'm currently working on a python package that I want to upload to pypi.
In the future, other devs will install this package via pip install and then load it into their .py files using import name_of_package.
In order to function properly, my python package needs to import another .py file from the same folder that it was imported into.
So let's assume someone works in /documents/python/some_project/ and he imports my package into his main.py script. My package script shall then search for a file called secondary.py in the same folder where main.py is located, namely /documents/python/some_project/ and then import secondary.py into the package script.
How can I write this import statement in my package script?
The classic approach is to use relative imports;
from .other_module import foo_function
from .other_module import BarClass
See The import statement in the Python doc.
You can also take a look at importlib.import_module.
But, in your specific case, you want to call an external Python script located potentially anywhere in the user directory.
For that, you can use exec function. But, make sur the code your are calling is safe code.
When you use pip install, the installed package is stored in the virtualenv of the user; not in the user’s source directory. I think you are also confused by that.

How are modules are installed and located?

I need help to troubleshoot the installation of gspread for an GAE app.
On my Windows PC, I have python.exe in C:\python27.
I installed gspread by running its setup.py from its distribution folder as follows:
c:\python27\python.exe setup.py install --home=X
The following folder and files were created in X\lib\python:
request-2.9.1-py2.7.egg (a folder)
easy-install.pth
gspread-0.2.5-py2.7.egg
site.py
Why lib\python? Is this sub-folder hardcoded somewhere?
When I launch my Python interpreter, I can then import gspread. sys.path includes the fully qualified path to X\lib\python\gspread-0.2.5-py2.7.egg. Note it's a path to a file and not a folder.
How does Python know where to locate gspread? I tried looking in C:\python27 for clues but could not find anything related to gspread, not even in the site-packages folder.
Python searches sys.path in order. It is likely that Python is importing gspread using the contents of the egg. Note that if Python finds a match before the gspread egg, it will stop on the first matching entry in sys.path. For example if you have a module named gspread in the current working directory, then Python will not use the egg.
If you want to modify the package, you have many different options. I suggest to first uninstall the current egg. Then place the folder named gspread in site-packages.
An even better alternative is to add the gspread source directory to PYTHONPATH. You can change the PYTHONPATH environment variable by
My Computer -> Properties -> Advanced > Environment Variables
When you defined --home option setuptools is simulating linux Home directory thats why the installation location goes to X:\lib\python.
My guess is this home path is getting added to Python env on the system sorry I don't have windows to test this but there is some info here: https://docs.python.org/2.3/inst/alt-install-windows.html

How to organize a python project that has both an executable and a package with the same name

I often create python projects that offer both a package and an executable where it makes sense to call them by the same name. For example, I created a password program utility abraxas that includes a program that generates passwords for me, and also provides a python library package that allows me to access passwords from other python scripts. Whenever I do this I struggle with organizing my files. I have the following constraints that I am trying to satisfy:
Once installed, both the executable and the library should have the same name to highlight the relationship between the two (meaning that I would like to run the program using 'abraxas' and import the package with 'import abraxas').
I must be able to run the program from the source directory without formally installing the executable (to speed up debugging).
I must be able to directly import the package into the executable.
I would like to avoid hacking sys.path.
I am using linux, so I don't want to add silly extensions to my executable, such as .exe.
Normally the executable and package would be in the same directory, but this does not work in this case because the names conflict.
Alternatively, I could place the executable in a different directory, but then the program would not run without first installing it because it cannot naturally find the package.
The only solution I have found to this problem is to change the name of the executable in my source directory and place it next to the package directory; then rename the executable after installing it.
Can anyone suggest a better solution to this problem?

PYTHONPATH issues with versioned package names outside of site-packages

In attempting to solve a package management issue here, I learned I may have issues with the way I'm using PYTHONPATH to access packages outside of the site-packages directory.
I receive an import error when attempting to import modules from a package (say wxPython) from its versioned directory folder name (i.e. wx-2.8-msw-unicode) when said directory is not in the python site-packages directory.
To recreate the issue: Create a directory outside of the python directory, say C:\foo. Download wxPython, and place it in that directory (giving C:\foo\wx-2.8-msw-unicode). Add more if you like. Add the directory C:\foo to your PYTHONPATH environment variable. Open a new python interactive shell and run
import sys
for i in sys.paths:
print i
to verify that the path is there (which it is), then
import wx
I receive an Import Error. What am I doing wrong? Is this behavior correct?
As I understand what you're saying, this is expected behaviour. C:\foo is in your Pythonpath, but it does not contain an importable wx module. For import wx to succeed, it has to find one of wx.(py/pyc/pyd/dll/so) or a directory wx containing the file __init__.py, directly in one of the directories on your Pythonpath.
The installer will normally sort out making sure this is in an importable location for you. If you want to do it yourself, you have to ensure that wx ends up in an importable location.

Python: using downloaded modules

I am new to Python and mostly used my own code. But so now I downloaded a package that I need for some problem I have.
Example structure:
root\
externals\
__init__.py
cowfactory\
__init__.py
cow.py
milk.py
kittens.py
Now the cowfactory's __init__.py does from cowfactory import cow. This gives an import error.
I could fix it and change the import statement to from externals.cowfactory import cow but something tells me that there is an easier way since it's not very practical.
An other fix could be to put the cowfactory package in the root of my project but that's not very tidy either.
I think I have to do something with the __init__.py file in the externals directory but I am not sure what.
Inside the cowfactory package, relative imports should be used such as from . import cow. The __init__.py file in externals is not necessary. Assuming that your project lies in root\ and cowfactory is the external package you downloaded, you can do it in two different ways:
Install the external module
External Python packages usually come with a file "setup.py" that allows you to install it. On Windows, it would be the command "setup.py bdist_wininst" and you get a EXE installer in the "dist" directory (if it builds correctly). Use that installer and the package will be installed in the Python installation directory. Afterwards, you can simply do an import cowfactory just like you would do import os.
If you have pip or easy_install installed: Many external packages can be installed with them (pip even allows easy uninstallation).
Use PYTHONPATH for development
If you want to keep all dependencies together in your project directory, then keep all external packages in the externals\ folder and add the folder to the PYTHONPATH. If you're using the command line, you can create a batch file containing something like
set PYTHONPATH=%PYTHONPATH%:externals
yourprogram.py
I'm actually doing something similar, but using PyDev+Eclipse. There, you can change the "Run configurations" to include the environment variable PYTHONPATH with the value "externals". After the environment variable is set, you can simply import cowfactory in your own modules. Note how that is better than from external import cowfactory because in the latter case, it wouldn't work anymore once you install your project (or you'd have to install all external dependencies as a package called "external" which is a bad idea).
Same solutions of course apply to Linux, as well, but with different commands.
generally, you would use easy_install our pip to install it for you in the appropriate directory. There is a site-packages directory on windows where you can put the package if you can't use easy_install for some reason. On ubuntu, it's /usr/lib/pythonX.Y/dist-packages. Google for your particular system. Or you can put it anywhere on your PYTHONPATH environment variable.
As a general rule, it's good to not put third party libs in your programs directory structure (although there are differing opinions on this vis a vis source control). This keeps your directory structure as minimalist as possible.
The easiest way is to use the enviroment variable $PYTHONPATH. You set it before running your scripts as follows:
export $PYTHONPATH=$PYTHONPATH:/root/externals/
You can add as many folders as you want (provided their separate by :) and python will look in all those folders when importing.

Categories