ModuleNotFoundError: No module named '<Directory name>' - python

When I call python __main__.py
I receive error:
from facebook.fb_api import FacebookApi
ModuleNotFoundError: No module named 'facebook'
# __main__.py
from facebook.fb_api import FacebookApi
if __name__ == "__main__":
api = FacebookApi()
api.start()
Project structure
facebook/
├── cache.py
├── configs.py
├── fb_api.py
├── __init__.py
├── __main__.py
├── parser
│   ├── cfg.py
│   ├── example.json
│   ├── __init__.py
│   ├── models.py
│   ├── run_parser.py
│   └── utils.py
├── __pycache__
│   └── fb_api.cpython-36.pyc
├── request_handler.py
└── services
├── case_service.py
└── __init__.py

Your fb_api.py is in the same directory as __main__.py so no facebook folder exists for your application. Remove it from your import and it should work

Because __main__.py is in the same directory. So just import fb_api. To use Facebook.fb_api then move main.py to Facebook directory.

You need to run your code from a higher level in your directory structure. Rather than running from within the facebook folder, run from its parent folder with python -m facebook. The -m flag tells Python you're running module by its Python name, which in this case is the facebook package. A package being run that way has its __main__.py file run as the main script, which is exactly what you want.

Try local import
# __main__.py
from .fb_api import FacebookApi
if __name__ == "__main__":
api = FacebookApi()
api.start()

Related

How to run coverage for a Python project with src-layout?

My python project is structured in the so called src-layout.
hyperorg
├── README.md
├── setup.cfg
├── setup.py
├── src
│   └── hyperorg
│   ├── content.py
│   ├── exporter.py
│   ├── __init__.py
│   ├── __main__.py
│   └── reader.py
└── tests
├── helper.py
├── __init__.py
├── test_content.py
├── test_exporter.py
├── test_hyperorg.py
└── test_reader.py
I am not able to get coverage running for it. How can I do this?
What I tried so far
Run coverage in the projects root folder just gives me Nothing to run.
Or coverage run ./src/hyperorg gives me
Traceback (most recent call last):
File "/home/user/tab-cloud/hyperorg/src/hyperorg/__main__.py", line 6, in <module>
from .content import Content
ImportError: attempted relative import with no known parent package
One of the ways of doing that is entering the src folder by cd src and then running coverage from there as following:
coverage run -m unittest discover -s ../tests
You can also leverage rcfile (default .coveragerc) to specify configurations and change HTML report path to be created outside the src folder as well.

Python executable script ModuleNotFound

I am trying to better understand importing modules. I read about how to do this from here https://stackoverflow.com/a/14132912/14179793 and I can get it to work using solution 1. There is an additional variable that I need to figure out though.
This is a dummy project I am testing with:
.
├── a_package
│   ├── __init__.py
│   └── lib_a.py
├── b_package
│   ├── __init__.py
│   └── test_script.py
├── main.py
└── src
└── src_lib
└── src_lib.py
With this setup I can do:
python -m b_package.test_script
this is lib a function
This is src_lib_function.
test_script.py:
from a_package.lib_a import lib_a_function
from src.src_lib.src_lib import src_lib_function
if __name__ == '__main__':
lib_a_function()
src_lib_function()
pass
The goal is to make b_package/test_script.py executable without using python test_script ie ./test_script
However, adding the shebang at the top #!/usr/bin/env python causes an import error:
$ ./b_package/test_script.py
Traceback (most recent call last):
File "./b_package/test_script.py", line 2, in <module>
from a_package.lib_a import lib_a_function
ModuleNotFoundError: No module named 'a_package'
I assume it is because python is not loading it as a module based off the above mentioned question but I am not sure how to resolve this.
I ended up using setuptools as suggested by kosciej16 to achieve the desired results.
New project structure:
.
├── a_package
│   ├── __init__.py
│   └── lib_a.py
├── b_package
│   ├── __init__.py
│   └── test_script.py
├── main.py
├── pyproject.toml
├── setup.cfg
└── src
├── __init__.py
└── src_lib
├── __init__.py
└── src_lib.py
setup.cfg:
[metadata]
name = cli_test
version = 0.0.1
[options]
packages = find:
[options.entry_points]
console_scripts =
test_script = b_package.test_script:main
This allows the user to clone the repo and run pip install . from the top level then they can execute the script by just typing test_script

ModuleNotFoundError: No module named 'python'

I have a python project and want to write a command line launcher. My project works fine when I run tests or launch from my IDE (pycharm). However when I try to launch via the command line I get a ModuleNotFoundError: No module named 'python' error.
Here is my directory structure:
.
├── Makefile
├── Pipfile
├── Pipfile.lock
├── README.md
├── create_jenkins_jobs.sh
└── python
├── __init__.py
├── create_credentials.py
├── create_jenkins_jobs_cli.py
├── credential_builder.py
├── jenkins_multibranch_job_builder.py
├── templates
│   ├── job.xml
│   ├── multibranch_job_template.xml
│   ├── ssh_cred_template.xml
│   └── user_pw_cred_template.xml
└── tests
├── __init__.py
├── integration
│   ├── __init__.py
│   ├── build_credential_test.py
│   ├── build_job_test.py
│   ├── conftest.py
│   ├── test_id_rsa
│   └── test_id_rsa.pub
└── unit
The shell script create_jenkins_jobs.sh contains:
#!/bin/bash
python3 python/create_jenkins_jobs_cli.py "${#}"
the file create_jenkins_jobs_cli.py contains the following code:
from typing import Set
from shared.common import preflight_env_check
from python.jenkins_multibranch_job_builder import JenkinsMultibranchJobBuilder
def configure_jenkins_jobs(git_repos: Set[str]):
jenkins_job_builder = JenkinsMultibranchJobBuilder(jenkins_server_url=JENKINS_BASE_SERVER_URL,
jenkins_folder=JENKINS_ROOT_JOB_FOLDER,
user=JENKINS_USER, token=JENKINS_TOKEN,
git_cred_id=GIT_SSH_CRED_ID,
git_repos=git_repos)
jenkins_job_builder.configure_jobs()
configure_jenkins_jobs(GIT_REPOS)
When I launch create_jenkins_jobs.sh or create_jenkins_jobs_cli.py I always get
ModuleNotFoundError: No module named 'python'
$>./create_jenkins_jobs.sh
/Users/pswenson/dev/cc-cicd-automation/.venv/bin/python3: Error while finding module specification for 'python/create_jenkins_jobs_cli.py' (ModuleNotFoundError: No module named 'python/create_jenkins_jobs_cli')
I've tried all sorts of different techniques to get this to work with PYTHONPATH, working directories, etc...
It seems there is something basic about how python modules work that I don't understand.
Does changing the line:
from python.jenkins_multibranch_job_builder import JenkinsMultibranchJobBuilder
to
from jenkins_multibranch_job_builder import JenkinsMultibranchJobBuilder
Sort you?

When package has same name as .py file inside the package, import X imports the module and not the package itself. How to avoid?

So the package Im constructing looks something like this:
Blur/
├── blur
│   ├── __init__.py
│   ├── blur.py
│   ├── funcs
│   │   ├── __init__.py
│   │   ├── face_funcs.py
│   │   └── funcs.py
│   ├── tests
│   │   ├── __init__.py
│   │   └── test_blur.py
│   └── utils
│   ├── __init__.py
│   └── timer.py
└── setup.py
Doing import blur imports blur.py module, and not the whole package itself. If I change blur.py's name, then do the import, i get the whole package. Any way to get the whole package without changing blur.py's name?
If you specify the file path to the "Blur" folder in the import statement, that should force python to import the package, and not the .py file. I believe by default python looks for files ending in .py when importing.
AFAIK it is not possible as a built-in Python mechanism, so changing the name would be your best bet.
There are, however, workarounds available, but in my opinion such solutions are rather ugly.
Here is an example:
import importlib
import os
import sys
def custom_import(repo_path, directory, package=False):
absolute_path = repo_path if package else os.path.join(repo_path, directory)
if os.path.exists(absolute_path):
sys.path.insert(0, absolute_path)
if package:
imported = importlib.import_module(f'{directory}')
else:
imported = importlib.import_module(f'{directory}.{directory}')
sys.path.pop(0)
return imported
raise ImportError(' No such package/module found')
Example use:
package = custom_import('D:\PycharmProjects\python-tools', 'roomba', package=True)
module = custom_import('D:\PycharmProjects\python-tools', 'roomba')
module.main()

Python2.7 import: recognises directory but not modules within

I'm trying to import the module my_app/common/model/Model.py into the file /my_app/common/database/db_update.py. My PYTHONPATH points to app/common/. However, when I try to do so, I get the error message:
File "/home/me/my_app/common/database/db_update.py", line 26, in <module>
import model.Model
ImportError: No module named Model
A simplified representation of my file structure is as follows:
common/
├── customlogger
│   ├── __init__.py
│   ├── __init__.pyc
│   ├── logger.py
│   └── logger.pyc
├── database
│   ├── DBSetup.py
│   ├── DBSetup.pyc
│   ├── db_update.py
│   ├── db_update.pyc
│   ├── __init__.py
│   └── __init__.pyc
├── __init__.py
├── __init__.pyc
└── model
├── __init__.py
├── __init__.pyc
├── Model.py
└── Model.pyc
The head of the db_update.py file contains the following imports (amongst others) in this order:
import customlogger.logger
import database.DBSetup
import model.Model
Some information that may be useful:
I have tried importing other modules from the model/ directory. These are also not recognised and result in the same error (with the respective module's name instead).
I am running a bash script to do this, from a directory adjacent to common/ - call it my_app/src/.
All my __init__.py files are empty.
I'm running Ubuntu 14.04.
It seems to me that python recognises the model/ directory (else, the error message would read ImportError: No module named model.Model), but seems to think that it doesn't contains any modules despite the presence of the __init__.py file. Is this the case? And if so, why does this happen exclusively in the model/ directory and not the database/ nor the customlogger/ directories? Finally, how can I fix this?
Many thanks in advance.

Categories

Resources