开发者

How is a Python project set up?

I am doing some heavy commandline stuff (n开发者_C百科ot 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?


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. Don't Repeat Yourself.

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).


Each python source file is a module. There are no "header" files. The basic idea is that when you import "foo" it'll load the code from "foo.py" (or a previously compiled version of it). You can then access the stuff from the foo module by saying foo.whatever.

There seem to be two ways for arranging things in Python code. Some projects use a flat layout, where all of the modules are at the top-level. Others use a hierarchy. You can import foo/bar/baz.py by importing "foo.bar.baz". The big gotcha with hierarchical layout is to have __init__.py in the appropriate directories (it can even be empty, but it should exist).

Classes are defined like this:

class MyClass(object):
    def __init__(self, x):
        self.x = x

    def printX(self):
        print self.x

To create an instance:

z = MyObject(5)


You can organize it in whatever way makes the most sense for your application. I don't exactly know what you're doing so I can't be certain what the best organization would be for you, but you can pretty much split it up as you see fit and just import what you need.

You can define classes in any file, and you can define as many classes as you would like in a script (unlike Java). There are no official header files (not like C or C++), but you can use config files to store info about connecting to a DB, whatever, and use configparser (a standard library function) to organize them.

It makes sense to keep like things in the same file, so if you have a GUI, you might have one file for the interface, and if you have a CLI, you might keep that in a file by itself. It's less important how your files are organized and more important how the source is organized into classes and functions.


This would be the place to look for that: http://docs.python.org/reference/.

First of all, compile and install pip: http://pypi.python.org/pypi/pip. It is like Ubuntu's apt-get. You run it via a Terminal by typing in pip install package-name. It has a database of packages, so you can install/uninstall stuff quite easily with it.

As for importing and "header" files, from what I can tell, if you run import foo, Python looks for foo.py in the current folder. If it's not there, it looks for eggs (folders unzipped in the Python module directory) and imports those.

As for defining classes and objects, here's a basic example:

class foo(foobar2): # I am extending a class, in this case 'foobar2'. I take no arguments.
  __init__(self, the, list, of, args = True): # Instead, the arguments get passed to me. This still lets you define a 'foo()' objects with three arguments, only you let '__init__' take them.
    self.var = 'foo'

  def bar(self, args):
    self.var = 'bar'

  def foobar(self):  # Even if you don't need arguments, never leave out the self argument. It's required for classes.
    print self.var

foobar = foo('the', 'class', 'args') # This is how you initialize me!

Read more on this in the Python Reference, but my only tip is to never forget the self argument in class functions. It will save you a lot of debugging headaches...

Good luck!


There's no some fixed structure for Python programs, but you can take Django project as an example. Django project consists of one settings.py module, where global settings (like your example with DB connection properties) are stored and pluggable applications. Each application has it's own models.py module, which stores database models and, possibly, other domain specific objects. All the rest is up to you.

Note, that these advices are not specific to Python. In C/C++ you probably used similar structure and kept settings in XML. Just forget about headers and put settings in plain in .py file, that's all.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜