Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Import binary package from different directory

I have the following directory structure:

root
  /src
    file1.py
    file2.py
  /libs
    __init__.py
    package.so

I wish to import package.so within file1.py.

I've tried the following import statements to no avail:

from .libs.package import func
from libs.package import func
from .libs import package
from libs import package

I want to avoid having to set PYTHONPATH / sys.path.

Is there a simple way to do this? I assume the issue is due to the package being a shared object and not just a Python file - I don't have access to the source code for it.

Thanks, Adam

like image 468
amitchone Avatar asked Jun 22 '18 14:06

amitchone


People also ask

How do I import a module from another folder?

The most Pythonic way to import a module from another folder is to place an empty file named __init__.py into that folder and use the relative path with the dot notation. For example, a module in the parent folder would be imported with from .. import module .

How can I import modules if file is not in same directory?

We can use sys. path to add the path of the new different folder (the folder from where we want to import the modules) to the system path so that Python can also look for the module in that directory if it doesn't find the module in its current directory.

How do I import a module from the root directory?

In order to import a module, the directory having that module must be present on PYTHONPATH. It is an environment variable that contains the list of packages that will be loaded by Python. The list of packages presents in PYTHONPATH is also present in sys. path, so will add the parent directory path to the sys.


1 Answers

If you are intent on not using sys.path.append to import the file, I was able to do it using the following snippet in file1.py:

import imp
import os
file = os.sep+os.path.join(*os.path.realpath(__file__).split(os.sep)[:-1]+['..','libs','package.so'])
package = imp.load_source('root.libs.package', file)
print package.a()

Which prints <root.libs.package.a instance at 0x101845518>. Note that my package.so file is just a python file that defines a dummy class a so that I could test importing it. From what I have read, I believe that replacing imp.load_source with imp.load_dynamic may be what you want.

Breaking it down:

os.path.realpath(__file__).split(os.sep)[:-1] gets you the path to the directory the currently-running script is in, as a list of strings.

+['..','libs','package.so'] concatenates a list containing the parent directory (..), the libs directory, and your filename to that list, so that os.path.join will build the full path to the package.so file.

os.path.join(*[that list]) unpacks the list elements into arguments to os.path.join, and joins the strings with os.sep. I also add a leading os.sep since it is an absolute path.

imp.load_source returns a module with the name root.libs.package loaded from the file path.

This source was useful for writing this answer, and here are the docs for the imp module, which you might also find useful.

like image 110
MoxieBall Avatar answered Oct 21 '22 10:10

MoxieBall