1

I have a directory structure that looks like this:

foo/
   __init__.py
   db.py
   database.db
main.py

Now, in db.py, I read the contents of the database:

open('database.db').read()

This works as long as I am running db.py directly. However, when I try to import the foo package in main, and then run db.py, it fails with a file not found error.

How can I avoid this? (Preferably without making any changes to the modules in the foo package)

(Note: I am aware of a solution like this Relative paths in Python but that would entail a lot of modifications to my foo package)

EDIT 1: Is it not possible to add something to __init__.py so that python can find my files?

EDIT 2: As another small example, consider what happens when I start to have nested packages:

foo/
  baz/
    __init__.py
    mod.py
    modules.json
  __init__.py
  db.py
  database.py
main.py

Now, if main.py uses the foo package, and db.py requires the baz package, then I need to start making more complicated changes in the modules of the baz as well as the foo package, so that the file reads succeed.

This kind of a situation is happening when I need to use a git module that has several nested submodules. Obviously, it's not very convenient to make so many changes.

Community
  • 1
  • 1
Dizzy
  • 129
  • 7
  • What modification to `foo` package would http://stackoverflow.com/questions/918154/relative-paths-in-python entail? As I see it, it would only entail changes to `db.py` . – Anand S Kumar Aug 05 '15 at 10:16
  • @AnandSKumar this is obviously a small example, but there are a lot of references like this. Is it not possible to add something to `__init__.py` so that python can find my files? – Dizzy Aug 05 '15 at 10:18
  • in python3 i like `from pathlib import Path; HERE = Path(__file__).parent`. you could define that in your `__init__` and then use things like `DATA_PATH = HERE / '../data/test.csv'`. – hiro protagonist Aug 05 '15 at 10:47

2 Answers2

1

One solution can be to mask the open() function with a function of your own, in db.py , and in that custom open() function, you can open the file after appending the directory of __file__ . Example -

def open(file,mode='r',buffering=-1):
    import __builtin__    #use import builtins for Python 3.x
    import os.path
    filePath = os.path.join(os.path.dirname(__file__),file)
    return __builtin__.open(filePath,mode,buffering)

__builtin__.open() (or for Python 3.x - builtins.open() ) points to the built-in open() function.

I have used buffering =-1 as it seems to be the default according to documentation , you can leave out that argument altogether, if its not needed.

If possible, you should not mask (maybe use a different name like - open_file() ) , but seems like you do not want to do that.

Though I still think masking should be done only when there is no other solution. Also, please note you should not be import db.py as from db import * , that may cause similar masking of open() in the other .py file where its imported (Ideally, it is not recommended to do from <module> import * in any situtation) .

Anand S Kumar
  • 88,551
  • 18
  • 188
  • 176
  • Please have a look at my updated question, to see how problematic this is becoming :/ – Dizzy Aug 05 '15 at 11:03
  • With this solution you just need to add the above function as the first function in all py files, thats it, no other changes. – Anand S Kumar Aug 05 '15 at 11:05
  • The only other way i can think of is to change directory to that module, but that would not work, because `__init__.py` is only run when the module is imported first time, not always when modules are imported. – Anand S Kumar Aug 05 '15 at 11:06
  • Hmm, this seems to be the only solution then. Ok. Thanks. – Dizzy Aug 05 '15 at 11:11
0

Use of this module will to resolve this import error issue, the error that you mentioned is issue about path. so the error was python interpreter coulnt find the path where your modules has specified. if you use this module it would work fine.

 sys.path 

A list of strings that specifies the search path for modules. Initialized from the environment variable PYTHONPATH, plus an installation-dependent default

import sys
sys.path.append('..\Desktop\New folder')# folder destination
from foo import db
Moorthi Muthu
  • 409
  • 5
  • 13