Understanding python imports

2019-02-15 10:52发布

问题:

In the process of learning Django and Python. I can't make sense of this.

(Example Notes:'helloworld' is the name of my project. It has 1 app called 'app'.)

from helloworld.views import *          # <<-- this works
from helloworld import views            # <<-- this doesn't work
from helloworld.app import views        # <<-- but this works.  why?

It seems like line #2 and #3 are practically the same. Why does like #2 not work?

Edit -- Added the source of the two files. You might recognize this code from the Django Book project (http://www.djangobook.com/en/2.0)

helloworld/views.py

from django.shortcuts import render_to_response
from django.http import HttpResponse, Http404
import datetime

def hello(request):
    return HttpResponse("Hello world")


def current_datetime(request):
    current_date = datetime.datetime.now()
    return render_to_response('current_datetime.html', locals())


def offset_datetime(request, offset):
    try:
        offset = int(offset)
    except ValueError:
        raise Http404()

    next_time = datetime.datetime.now() + datetime.timedelta(hours=offset)
    return render_to_response('offset_datetime.html', locals())

def display_meta(request):
    values = request.META.items()
    values.sort()
    path = request.path
    return render_to_response('metavalues.html', locals())

helloworld/app/views.py

from django.shortcuts import render_to_response

def search_form(request):
    return render_to_response('search_form.html')

def search(request):
    if 'q' in request.GET:
        message = 'You searched for: %r' % request.GET['q']
    else:
        message = 'You searched for nothing.'

    return render_to_response('search_results.html', locals())

回答1:

Python imports can import two different kinds of things: modules and objects.

import x

Imports an entire module named x.

import x.y

Imports a module named y and it's container x. You refer to x.y.

When you created it, however, you created this directory structure

x
    __init__.py
    y.py

When you add to the import statement, you identify specific objects to pull from the module and move into the global namespace

import x # the module as a whole
x.a # Must pick items out of the module
x.b

from x import a, b # two things lifted out of the module
a # items are global
b

If helloworld is a package (a directory, with an __init__.py file), it typically doesn't contain any objects.

from x import y # isn't sensible
import x.y # importing a whole module.

Sometimes, you will have objects defined in the __init__.py file.

Generally, use "from module import x" to pick specific objects out of a module.

Use import module to import an entire module.



回答2:

from helloworld.views import *          # <<-- this works
from helloworld import views            # <<-- this doesn't work
from helloworld.app import views        # <<-- but this works.  why?

#2 and #3 are not the same.

The second one imports views from the package helloworld. The third one imports views from the package helloworld.app, which is a subpackage of helloworld. What it means is that views are specific to your django apps, and not your projects. If you had separate apps, how would you import views from each one? You have to specify the name of the app you want to import from, hence the syntax helloworld.app.



回答3:

As sykora alluded, helloworld is not in-and-of-itself a package, so #2 won't work. You would need a helloworld.py, appropriately set up.

I asked about import a couple of days ago, this might help: Lay out import pathing in Python, straight and simple?