1

I've a flask application cloned from git after installing all of its requirements and starting the app by

$ python start.py

I get the following error

Traceback (most recent call last):
  File "start.py", line 6, in <module>
    app = create_app("local")
  File "C:\Jahangeer\qurbcode\api\app\__init__.py", line 66, in create_app
    from app.api_1_0 import apibp as api_1_0, api_spec as api_1_0_spec
  File "C:\Jahangeer\qurbcode\api\app\api_1_0\__init__.py", line 78, in <module>
    ModuleImport.importModulesFromPath(os.path.dirname(os.path.realpath(__file__)), __name__)
  File "C:\Jahangeer\qurbcode\api\app\helpers\module_import.py", line 16, in importModulesFromPath
    importlib.import_module("." + module, package)
  File "C:\Python27\lib\importlib\__init__.py", line 37, in import_module
    __import__(name)
ImportError: Import by filename is not supported.

Start.py have the following code

import os
from app import create_app

app = create_app("local")

if __name__ == '__main__':
    app.run(host= '0.0.0.0', threaded=True)

and Inside my init.py on line 66 which is mentioned in above error has the following

 # Setup api/1.0 blueprint
    from .api_1_0 import apibp as api_1_0, api_spec as api_1_0_spec
    from .admin import admin_bp as admin
    app.register_blueprint(api_1_0, url_prefix='/api/1.0')

Here is application structure

api
->admin_app
->app
  ->admin
  ->api_1_0
  ->__init__.py
->start.py
->manage.py

My api\app\helpers\module_import.py have the following code:

import glob
import importlib


class ModuleImport:

    @staticmethod
    def importModulesFromPath(dir_path, package, import_init = False):
        files = glob.glob(dir_path + "/*.py")
        for file in files:
            module = file.replace(dir_path, "").replace("/", "").replace(".py", "")

            if module == "__init__" and not import_init:
                continue

            importlib.import_module("." + module, package)

and my api\app\api_1_0__init__.py have the following code: on line 78

ModuleImport.importModulesFromPath(os.path.dirname(os.path.realpath(__file__)), __name__)
davidism
  • 121,510
  • 29
  • 395
  • 339
Jahangeer
  • 486
  • 1
  • 6
  • 20
  • It looks like your problem's actually happening a bit lower down in your application. Could you also drop the context for `api\app\api_1_0\__init__.py` and `api\app\helpers\module_import.py`? It looks like you've got some kind of home-rolled module importing setup, and that's probably what's causing you issues. – ymbirtt Nov 27 '18 at 08:48
  • 1
    @ymbirtt please review the edited question again. Posted code of both file – Jahangeer Nov 27 '18 at 09:00

2 Answers2

1

Your autoloader is almost certainly doing a Bad Thing(tm).

It looks like your code is designed to be run on Linux, but you're running it on Windows. In and of itself, this isn't necessarily bad, but it's not written in a way that supports this. Specifically, glob.glob(dir_path + "/*.py") is returning you the paths to all the .py files in a directory, and they'll come out looking like C:\\path\\to\\file.py. Later, the chain module = file.replace(dir_path, "").replace("/", "").replace(".py", "") will try and strip the .py and the C:\\path\\to parts, leaving you with \\file, but .replace('/', '') won't remove that leading backslash, because it's looking for forward slashes and windows uses backslashes. You'll then attempt to import \\file, which you can't do because you can't pass a path to the __import__ function - that's not how that works.

In the short term, you might find that everything springs into life if you change your ModuleImport tool to have an import os at the top. Then replace dir_path + "/*.py" with os.path.join(dir_path, '*.py'), and replace("/", "") with replace(os.sep, ""). This should fix your immediate problem, but you shouldn't leave the code like that.

Longer term, this is not a good way to autoload modules, and if you're screwing around with importlib to get your modules to load properly, you can probably load your modules in a far better way. I usually consider it a code smell when I see things like sys.path.append or importlib.import knocking around. You might find that your code is easier to maintain if you look at How to load all modules in a folder?

ymbirtt
  • 1,481
  • 2
  • 13
  • 24
0

It's not a good idea to hard code paths.

You can use pathlib, if you're using Python 3, or os.path.join otherwise.

from pathlib import Path

data_folder = Path("source_data/text_files/")

file_to_open = data_folder / "raw_data.txt"

f = open(file_to_open)

print(f.read())

or even if you'd like to get the windows path:

from pathlib import Path, PureWindowsPath

filename = PureWindowsPath("source_data\\text_files\\raw_data.txt")

correct_path = Path(filename)

print(correct_path)
# "source_data/text_files/raw_data.txt" on Mac and Linux
# "source_data\text_files\raw_data.txt" on Windows
Julian Camilleri
  • 2,975
  • 1
  • 25
  • 34