Design: Module interface vs. library interface

Stefan Schwarzer sschwarzer at sschwarzer.net
Sat Sep 11 15:16:19 CEST 2010


Hello,

I maintain ftputil [1], an FTP client library.

Users of the library may use it like this:

| import ftputil
|
| with ftputil.FTPHost(server, userid, password) as ftp_host:
|     # for example, make a remote file and read its content
|     with ftp_host.open("remote_name", "rb") as remote_fobj:
|         data = remote_fobj.read()

Even though "ftp files" are defined in module `ftp_file` [2]
via class `FTPFile`, users of the ftputil library should
never use `FTPFile` directly; it's up to `FTPHost.open` to
generate these file objects.

Now, from the "point of view" of the _module_ `ftp_file`,
I'd use

| # ftp_file.py
|
| # used outside this module
| __all__ = ['FTPFile']
|
| class FTPFile(object):
|     ...

| # ftputil.py
|
| import ftp_file
|
| class FTPHost(object):
|     ...
|     def open(name, mode):
|         ...
|         return ftp_file.FTPFile(...)

On the other hand, from the point of view of the _library_
ftputil, `FTPFile` isn't part of the official API, so I may
as well write

| # ftp_file.py
|
| # be explicit, no user-public interface
| __all__ = []
|
| class FTPFile(object):
|     ...

Which approach would you prefer and why? Or some other
approach? Would you use a different approach if the
library-internal class was named `_FTPFile` instead of
`FTPFile`?

[1] http://ftputil.sschwarzer.net
[2] http://ftputil.sschwarzer.net/trac/browser/ftp_file.py

Stefan




More information about the Python-list mailing list