2

Say my project is structured like this:

myproject
├── calendar.py
├── foo.py
└── __init__.py

In foo.py, I have

from calendar import isleap

I thought in Python 3.x, without using the explicit .calendar the code above should load the build-in calendar module instead my own calendar module, but apparently my local calendar.py is still being imported and it throws an error because there's no 'isleap' in mypkg/calendar.py. Why was my local calendar module imported here?

I had to rename calendar.py to cal.py to get this work..

jfs
417k211 gold badges1k silver badges1.7k bronze badges
asked May 10, 2016 at 12:54
9
  • What is your question? Commented May 10, 2016 at 12:55
  • The question is..why is my local calendar module being loaded? Commented May 10, 2016 at 12:56
  • Because that is the first location that a module is being searched in. Commented May 10, 2016 at 13:03
  • 1
    That's normal. Python load the local module first. Commented May 10, 2016 at 13:10
  • 1
    @julivico ah..thanks..I was under the impression that the explicit import requires to use .calendar for the local module and without it it goes the build-in.. just my own imagination I suppose! :) I'm guessing the sensible way to solve this is to rename my module then.. Commented May 10, 2016 at 13:35

3 Answers 3

2

from __future__ import absolute_import is the default on Python 3. Therefore from calendar import isleap statement imports the top-level module calendar.

If you see other results; it means either you are not using Python 3 or you are trying to run a python module from inside a package as a script (myproject directory itself is in sys.path). If the latter then your calendar.py becomes the top-level module and (due to the current directory comes before stdlib directories in sys.path) from calendar import isleap imports calendar.py from the current directory. "Never add a package directory, or any directory inside a package, directly to the Python path"

To avoid it, do not run modules from within python packages directly e.g., do not do this: cd myproject; python foo.py. Do this instead: python -mmyproject.foo (or you could define what scripts should be run in setup.py or create a similar script manually: from myproject import foo; foo.main()).

If you want to run a Python package as a script then create myproject/__main__.py then run python -mmyproject.


If you want to do a relative import in Python 3; do it explicitly e.g., in myproject/foo.py:

from .calendar import something

Or do an absolute import:

from myproject.calendar import something
answered May 10, 2016 at 14:44
Sign up to request clarification or add additional context in comments.

Comments

2

It looks like your path or directory structure is set up wrong.

Given the following structure the full name of your calendar module should be myproject.calendar. You can check this by printing out the __name__ attribute of your module. For this to be the case, the path that your program uses to import local modules must be the folder containing myproject.

myproject
├── calendar.py
├── foo.py
└── __init__.py

It seems like the path you are using is actually myproject. Meaning calendar.py is turned into the root level module calendar, rather than myproject.calendar. Python prefers local modules to builtin ones, and so imports your calendar module.

More typically you might do something like this.

MyProjectFolder
├── main.py
└── myproject
 ├── calendar.py
 ├── foo.py
 └── __init__.py

And then run your program like this:

#! /bin/bash
cd /path/to/MyProjectFolder
python main.py
answered May 10, 2016 at 13:36

Comments

-1

Python will check your local modules and load them firstly by import.

from calendar import isleap will search the module calendar in your locale package firstly. If not found, it will import from the builtin library calendar.

from .calendar import isleap will only import from your locale module calendar. If not found, raises a exception ImportError.

That is why you should use relative import in a package.

You can do a trick like that to import the builtin library without checking of the local modules. But it's only a trick. I will never use it in production. You should better rename your module calendar.

import imp, sys
f, pathname, desc = imp.find_module("calendar", sys.path[1:])
calendar = imp.load_module("calendar", f, pathname, desc)
f.close()
from calendar import isleap
answered May 10, 2016 at 13:48

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.