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
  • 399,953
  • 195
  • 994
  • 1,670
Godsent
  • 950
  • 2
  • 8
  • 22
  • What is your question? – zondo May 10 '16 at 12:55
  • The question is..why is my local calendar module being loaded? – Godsent May 10 '16 at 12:56
  • Because that is the first location that a module is being searched in. – DeepSpace May 10 '16 at 13:03
  • 1
    That's normal. Python load the local module first. – qvpham May 10 '16 at 13:10
  • @julivico Thanks. http://stackoverflow.com/questions/12172791/changes-in-import-statement-python3 seems to suggest you have to use .calendar for local module ..Is it possible to let it load build-in module first? – Godsent May 10 '16 at 13:19
  • Yes, it's suggested to use `from .calendar import isleap`. But `from calendar import isleap` will do **fast** the same thing. – qvpham May 10 '16 at 13:32
  • 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.. – Godsent May 10 '16 at 13:35
  • related: [Relative imports in Python 3](http://stackoverflow.com/q/16981921/4279) – jfs May 10 '16 at 14:52
  • Does this answer your question? [Python3 correct way to import relative or absolute?](https://stackoverflow.com/questions/28400690/python3-correct-way-to-import-relative-or-absolute) – Ani Menon Jul 03 '20 at 05:19

3 Answers3

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
Dunes
  • 37,291
  • 7
  • 81
  • 97
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
jfs
  • 399,953
  • 195
  • 994
  • 1,670
-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
qvpham
  • 1,896
  • 9
  • 17