How is a Python project set up?

I am doing some heavy commandline stuff (not really web based) and am new to Python, so I was wondering how to set up my files/folders/etc. Are there "header" files where I can keep all the DB connection stuff?

How/where do I define classes and objects?

Answers


Just to give you an example of a typical Python module's source, here's something with some explanation. This is a file named "Dims.py". This is not the whole file, just some parts to give an idea what's going on.

#!/usr/bin/env python

This is the standard first line telling the shell how to execute this file. Saying /usr/bin/env python instead of /usr/bin/python tells the shell to find Python via the user's PATH; the desired Python may well be in ~/bin or /usr/local/bin.

"""Library for dealing with lengths and locations."""

If the first thing in the file is a string, it is the docstring for the module. A docstring is a string that appears immediately after the start of an item, which can be accessed via its __doc__ property. In this case, since it is the module's docstring, if a user imports this file with import Dims, then Dims.__doc__ will return this string.

# Units
MM_BASIC = 1500000
MILS_BASIC = 38100
IN_BASIC = MILS_BASIC * 1000

There are a lot of good guidelines for formatting and naming conventions in a document known as PEP (Python Enhancement Proposal) 8. These are module-level variables (constants, really) so they are written in all caps with underscores. No, I don't follow all the rules; old habits die hard. Since you're starting fresh, follow PEP 8 unless you can't.

_SCALING = 1
_SCALES = {
    mm_basic: MM_BASIC,
    "mm": MM_BASIC,
    mils_basic: MILS_BASIC,
    "mil": MILS_BASIC,
    "mils": MILS_BASIC,
    "basic": 1,
    1: 1
}

These module-level variables have leading underscores in their names. This gives them a limited amount of "privacy", in that import Dims will not let you access Dims._SCALING. However, if you need to mess with it, you can explicitly say something like import Dims._SCALING as scaling.

def UnitsToScale(units=None):
    """Scales the given units to the current scaling."""
    if units is None:
        return _SCALING
    elif units not in _SCALES:
        raise ValueError("unrecognized units: '%s'." % units)
    return _SCALES[units]

UnitsToScale is a module-level function. Note the docstring and the use of default values and exceptions. No spaces around the = in default value declarations.

class Length(object):
    """A length.  Makes unit conversions easier.

    The basic, mm, and mils properties can be used to get or set the length 
    in the desired units.
    >>> x = Length(mils=1000)
    >>> x.mils
    1000.0
    >>> x.mm
    25.399999999999999
    >>> x.basic
    38100000L
    >>> x.mils = 100
    >>> x.mm
    2.54
    """

The class declaration. Note the docstring has things in it that look like Python command line commands. These care called doctests, in that they are test code in the docstring. More on this later.

    def __init__(self, unscaled=0, basic=None, mm=None, mils=None, units=None):
        """Constructs a Length.

        Default contructor creates a length of 0.
        >>> Length()
        Length(basic=0)

        Length(<float>) or Length(<string>) creates a length with the given 
        value at the current scale factor.
        >>> Length(1500)
        Length(basic=1500)
        >>> Length("1500")
        Length(basic=1500)
        """

        # Straight copy
        if isinstance(unscaled, Length):
            self._x = unscaled._x
            return

        # rest omitted

This is the initializer. Unlike C++, you only get one, but you can use default arguments to make it look like several different constructors are available.

    def _GetBasic(self): return self._x
    def _SetBasic(self, x): self._x = x
    basic = property(_GetBasic, _SetBasic, doc="""
        This returns the length in basic units.""")

This is a property. It allows you to have getter/setter functions while using the same syntax as you would for accessing any other data member, in this case, myLength.basic = 10 does the same thing as myLength._SetBasic(10). Because you can do this, you should not write getter/setter functions for your data members by default. Just operate directly on the data members. If you need to have getter/setter functions later, you can convert the data member to a property and your module's users won't need to change their code. Note that the docstring is on the property, not the getter/setter functions.

If you have a property that is read-only, you can use property as a decorator to declare it. For example, if the above property was to be read-only, I would write:

    @property
    def basic(self):
        """This returns the length in basic units."""
        return self._x

Note that the name of the property is the name of the getter method. You can also use decorators to declare setter methods in Python 2.6 or later.

    def __mul__(self, other):
        """Multiplies a Length by a scalar.

        >>> Length(10)*10
        Length(basic=100)
        >>> 10*Length(10)
        Length(basic=100)
        """
        if type(other) not in _NumericTypes:
            return NotImplemented
        return Length(basic=self._x * other)

This overrides the * operator. Note that you can return the special value NotImplemented to tell Python that this operation isn't implemented (in this case, if you try to multiply by a non-numeric type like a string).

    __rmul__ = __mul__

Since code is just a value like anything else, you can assign the code of one method to another. This line tells Python that the something * Length operation uses the same code as Length * something. *D*on't *R*epeat *Y*ourself.

Now that the class is declared, I can get back to module code. In this case, I have some code that I want to run only if this file is executed by itself, not if it's imported as a module. So I use the following test:

if __name__ == "__main__":

Then the code in the if is executed only if this is being run directly. In this file, I have the code:

    import doctest
    doctest.testmod()

This goes through all the docstrings in the module and looks for lines that look like Python prompts with commands after them. The lines following are assumed to be the output of the command. If the commands output something else, the test is considered to have failed and the actual output is printed. Read the doctest module documentation for all the details.

One final note about doctests: They're useful, but they're not the most versatile or thorough tests available. For those, you'll want to read up on unittests (the unittest module).


Need Your Help

Change UrlManager for just one controller

php url yii url-rewriting url-routing

My Yii 1.x application has UrlManager configured to generate / use URLs like content/show.html:

C# access database issue

c# database database-connection

private void button1_Click(object sender, EventArgs e)

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.