Writing a library in python

What are libraries in Python?

Python library is a collection of functions and methods that allows you to perform many actions without writing your code. For example, the Python imaging library (PIL).is one of the core libraries for image manipulation in Python. … It makes use of Numpy, another library for numerical operations.

Let’s consider a simple .py file:

It defines two functions and binds one variable to a value (treated, by convention, as a constant, though it’s not read-only). Called as a script it would print Foo: Bar: Testing Some constant

This file is a Python library. Let’s say you named it silly.py and used it thus:

That’s all there is to it.

A Python “library” is simply a .py file located on the path for your installation of Python (possibly by way of your configuration files or PYTHONPATH environment variable … and normally including your current working directory). You call it’s filename with no extension to import it. When you do so all of the code is evaluated mostly as if you’d run the program as a script. (The one salient difference is that a special identifier __name__ is only bound to the value ‘__main__’ when you’re executing Python as a script … otherwise it has the module’s name bound to it.

This feature of Python: if __name__ == ‘__main__’: is useful because it allows every .py file to serve as both a script or standalone utility or application and as a library.

You *could* put stuff up above that “magic” line … print statements and code that opens files, connects to databases, etc. But that’s very poor form. You *should* only define functions and constants or default values above the if __name__ line. Further more you should define all the functions you wish to “export” from a given file (import into some other code outside of (conventionally *before* the if __name__ line.

Following that simple rule means that your scripts will all be libraries in addition to their other utility.

There actually isn’t anything special about the if __name__ construct. The semantics of the __name__ variable are special but the if statement is just a like any other. You could have something like if __name__ != ‘__main__’: … and define do anything you wanted in that block of code (suite of statements). You could have multiple if __name__ … blocks or write it as while __name__ == … which would make perfect sense for a game or daemon that’s intended to run forever (or until some conditions call a break statement or an explicit sys.exit() function from within the loop. (Nobody actually does that, that I’ve seen. But it’s perfectly valid Python code). (I’ve seen one example, ever, where someone wanted if __name__ != __main__: … and I don’t even remember why; it had something to do with a large corpus of code that had some special custom import semantics).

Note that it’s also possible to define larger collections of Python code, spanning multiple files, into a Python “package” Do do this all you need to do is create a file, possibly even empty, named __init__.py in the top level directory of your package. When the Python interpreter is searching its path then those directory names (containing __init__.py files) become valid for an import statement just like any other library. Here’s some more details on that: Structuring Your Project

You can also write code in C (or Go-lang or Rust … potentially in any language which compiles down to native binary and support a C FFI (foreign function interface) and link it against the Python C headers/libraries. (Normally one would use SWIG or Cython or Boost or some other helper code/utilities to perform such bindings).

When you compile these modules they will become DLLs (dynamically loadable modules) on MS Windows or “.so” (shared object) files on Linux and most forms of Unix … or .dylib on MacOS X. Any such files, found on your PYTHONPATH (as appropriate to your platform … the code linked into your Python interpreter) can also be imported. Those are binary libraries rather than “pure Python.”

It’s possible to start your library as a single .py file. Eventually choose to break it down into multiple .py files putting them into a directory named like the base name of your original .py file and adding the __init__.py marker (possibly shifting any initialization code into that). You could also re-implement your code in C or Go or Rust … compile it into a binary library module and either replace your .py with that or put the resulting file into your “package.”

The beauty of Python’s import semantics is in this little facet … the people using your library don’t have to worry about those implementation details. The same import statement work and provides completely compatible semantics whether the thing being imported is a .py file, a package (directory), a compile binary module (linked to the proper Python binary APIs, of course) or even packaged up in a .zip or .egg file (and added to the PYTHONPATH is if it were a directory). (Here’s some more on that: Modules and Imports).

Python offers remarkably advanced support for writing modules and libraries … and it was vastly better than the alternatives (Perl, TCL, and so on) which were commonly available in Python’s early days. It’s almost harder to avoid making your Python code into a library than it is to write and use libraries in a modular and re-usable fashion.