How to reference python package when filename contains a period

31,478

Solution 1

Actually, you can import a module with an invalid name. But you'll need to use imp for that, e.g. assuming file is named models.admin.py, you could do

import imp
with open('models.admin.py', 'rb') as fp:
    models_admin = imp.load_module(
        'models_admin', fp, 'models.admin.py',
        ('.py', 'rb', imp.PY_SOURCE)
    )

But read the docs on imp.find_module and imp.load_module before you start using it.

Solution 2

If you really want to, you can import a module with an unusual filename (e.g., a filename containing a '.' before the '.py') using the imp module:

>>> import imp
>>> a_b = imp.load_source('a.b', 'a.b.py')
>>> a_b.x
"I was defined in a.b.py!"

However, that's generally a bad idea. It's more likely that you're trying to use packages, in which case you should create a directory named "a", containing a file named "b.py"; and then "import a.b" will load a/b.py.

Solution 3

No, you can't import a python file as a module if its name contains a period (or a question mark, or exclamation mark, etc). A python module's name (not including the .py) must be a valid python name (ie can be used as a variable name).

Solution 4

The file is called models/admin.py. (Source)

That is, it should be called admin.py in a directory called models.

Then you can import using from models.admin import *, assuming that it is in your Python path.

Solution 5

Like below

Assume dir structure is like this:

C:.
│   script.py
│   
└───Parent
    └───Child
        ├───1.1
        │       main.py
        │       
        └───1.2

**assume you want to import main.py in script.py **

your main.py looks like below

def my_function():
  print("Hello from a function")

your script.py looks like below

from os import path
import importlib
from os.path import dirname
import sys
import importlib.util


def getPath():
    # your logic to get to the path
    return path.join(dirname(__file__),'Parent','Child','1.1','main.py')

file_path = getPath() 
module_name = 'main'

spec = importlib.util.spec_from_file_location(module_name, file_path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)

#call functions like this
module.my_function()

Check out this gist

Share:
31,478
Alexander Bird
Author by

Alexander Bird

I'm currently working for Itential.

Updated on November 20, 2021

Comments

  • Alexander Bird
    Alexander Bird over 2 years

    I am using django and I have a file named models.admin.py and I want to do the following idea in models.py:

    from "models.admin" import *
    

    however, I get a syntax error for having double quotes. But if I just do

    from models.admin import *
    

    then I get "ImportError: No module named admin"

    Is there any way to import from a python file that has a period in its name?

  • Cat Plus Plus
    Cat Plus Plus over 14 years
    load_source is obsolete since at least 1.5.
  • Cat Plus Plus
    Cat Plus Plus over 14 years
    Bad practice? imp is the mechanism behind import and __import__. More flexibility, but requires more code. Nothing magical about it, though.
  • shylent
    shylent over 14 years
    And machine code is the mechanism behind everything. More flexibility and.. see where I'm going? :)
  • Cat Plus Plus
    Cat Plus Plus over 14 years
    You obviously need to think twice if you really need to use it, but I don't see how using it is terribly wrong. ;) And it is used in production - see e.g. Trac - trac.edgewall.org/browser/trunk/trac/loader.py.
  • Edward Loper
    Edward Loper over 14 years
    True, though the non-obsolete way of doing it is quite a bit wordier: a_b = imp.load_module('a.b', open('a.b.py'), os.path.abspath('a.b.py'), ('.py', 'r', imp.PY_SOURCE))
  • shylent
    shylent over 14 years
    My main point is, that, perhaps it is not terribly wrong to use this (ok, my subjective opinion is that it is terribly wrong, but away with that), but it is certainly not particularly right to advise it to someone who doesn't quite grasp the concept of modules and packages yet.
  • Alexander Bird
    Alexander Bird over 14 years
    For the record, I never actually named my file that the instant I realized this was going to be complicated. But after Googling out of curiosity and failing to find the answer, I decided that I wanted both the answer (import imp) and the voice of accepted practice (don't use it) to be archived for future Googlers. :)
  • haridsv
    haridsv about 14 years
    I think the important point is that this is an invalid module name as per python style guide: python.org/dev/peps/pep-0008. However, in OP's case, if module name can't be changed, this solution seems like it is reasonable, as it uses well documented interface. In other words, it is unlikely for a future python minor release to change this behavor. If the solution involved undocumented features, it is a different matter and I would have agreed with shylent.
  • Alexander Bird
    Alexander Bird about 11 years
    A module is a file. To quote the docs you referenced: To support this, Python has a way to put definitions in a file and use them in a script or in an interactive instance of the interpreter. Such a file is called a module;
  • Trent
    Trent almost 10 years
    Do you have a reference handy for this?
  • Gabriel Reid
    Gabriel Reid almost 10 years
    The reference is the Python grammar spec (docs.python.org/2/reference/grammar.html). However, this actually only specifies what is allowed for the import statement -- as pointed out above in the accepted answer, it's technically possible to get around this by using the underlying import mechanisms.
  • Travis
    Travis over 9 years
    To try and make a case for this method of import, consider a naming convention for unit tests whereby code related to testing module x is kept in a file called 'x.test.py'. This works fine most of the time since the unit tests are not normally imported by other modules but if a developer wants to reuse the test for 'x' as the basis for additional testing (ie...maybe they want to test mutlithreaded use of x in a file called 'mtx.test.py') then they would find themselves needing to import 'x.test' which of course only works with the help of the 'imp' module.
  • Kevin
    Kevin over 9 years
    This is formally deprecated as of 3.3. The correct way is to fiddle with the classes in importlib.machinery, which IMHO is way more trouble than it's worth.
  • WattsInABox
    WattsInABox about 5 years
    I am working with a library where a version number has to be in the directory structure (not my choice). Since I have no choice, I need something like this so thanks for this answer!
  • Eric Burel
    Eric Burel almost 4 years
    What would be the best pattern for long names with multiple words? Naming a package, and thus a folder "awesome.project" will create issues, while "awesomeProject" seems an anti-pattern. Not sure I get this rule correctly: python.org/dev/peps/pep-0423/#id87
  • run_the_race
    run_the_race over 2 years
    Actually you can, see @SciTech Enthusiast answer