I found the solution to my issue, which I believe was a misunderstanding of PEP 420 -- Implicit Namespace Packages.
This page states that, since Python 3.3:
While looking for a module or package named "foo", for each directory in the parent path:
- If <directory>/foo/__init__.py is found, a regular package is imported and returned.
- If not, but <directory>/foo is found and is a directory, it is recorded and the scan continues with the next directory in the parent path.
If the scan completes without returning a module or package, and at least one directory was recorded, then a namespace package is created. The new namespace package:
- Has a __path__ attribute set to an iterable of the path strings that were found and recorded during the scan.
- Does not have a __file__ attribute.
As defined in the pkg_resources documentation:
A namespace package is a package that only contains other packages and modules, with no direct contents of its own.
My package, as I described it, fell into that category, which was not intended.
After adding an empty __init.py__ below the myProject/ directory I see this happening during the install step:
β― python setup.py build
running build
running build_py
creating build/lib
creating build/lib/myProject
copying myProject/__init__.py -> build/lib/myProject
copying myProject/cli.py -> build/lib/myProject
Before:
>>> myProject.__path__
_NamespacePath(['/path/myProject'])
>>> myProject.__file__
AttributeError: module 'myProject' has no attribute '__file__'
After:
>>> myProject.__path__
['/path/myProject']
>>> myProject.__file__
'/path/myProject/__init__.py'
Answer from Antoine Cotten on Stack OverflowI have the following project structure:
gammy-cli/
|__env/ (virtualenv directory)
|__gammy/
|__utils/
|__log.py
|____init__.py
|__ad_config.json
|___init__.py
|__cli.py
|__MANIFEST.in
|__README.rst
|__setup.cfg
|__setup.pyThese are all located in a virtualenv directory. When i run 'pip install .' from the 'gammy-cli' directory, everything installs fine but when I try to run 'gammy' at the terminal from the 'gammy-cli' directory, I am getting the "ModuleNotFoundError: No module named gammy" error.
Contents of setup.py below:
from setuptools import setup
requirements = [
'xlrd',
'ldap3',
'pyasn1'
]
def readme():
with open('README.rst') as f:
return f.read()
setup(
name='gammy',
version='0.1',
description="Basic CLI tool to automate Google group management",
long_description=readme(),
author='bob bob,
author_email='bob@company.com',
url='https://github.com/bob/gammy',
entry_points = {'console_scripts': ['gammy=gammy.cli:main',],},
install_requires=requirements,
zip_safe=False,
classifiers=[
'Development Status :: 3 - Alpha',
'Natural Language :: English',
'Operating System :: MacOS X',
'Programming Language :: Python 3.6',
],
)After i run the pip install . command it seems to create a 'gammy' executable in the gammy-cli/env/bin/ directory. Not sure if that matters. This is my first attempt at trying to create a cli tool so any help would be appreciated. Been looking at this for a few days and googling a lot but haven't found a working solution or a way to diagnose the issue.
`ModuleNotFoundError` when running script from `console_scripts` but not when importing via Python console - Stack Overflow
python - ImportError when using console_scripts in setuptools - Stack Overflow
setuptools integration using "Scripts in Packages" example - not working
Bug: ModuleNotFoundError: No module named 'nibe_mqtt.console_scripts'
This issue arises due to the ways in which the command line IPython interpreter uses your current path vs. the way a separate process does (be it an IPython notebook, external process, etc). IPython will look for modules to import that are not only found in your sys.path, but also on your current working directory. When starting an interpreter from the command line, the current directory you're operating in is the same one you started ipython in. If you run
import os
os.getcwd()
you'll see this is true.
However, let's say you're using an ipython notebook, run os.getcwd() and your current working directory is instead the folder in which you told the notebook to operate from in your ipython_notebook_config.py file (typically using the c.NotebookManager.notebook_dir setting).
The solution is to provide the python interpreter with the path-to-your-module. The simplest solution is to append that path to your sys.path list. In your notebook, first try:
import sys
sys.path.append('my/path/to/module/folder')
import module_of_interest
If that doesn't work, you've got a different problem on your hands unrelated to path-to-import and you should provide more info about your problem.
The better (and more permanent) way to solve this is to set your PYTHONPATH, which provides the interpreter with additional directories look in for python packages/modules. Editing or setting the PYTHONPATH as a global var is os dependent, and is discussed in detail here for Unix or Windows.
Just create an empty python file with the name __init__.py under the folder which showing error, while you running the python project.
I feel like I've tried the usual stuff, but I remain stumped here. This code used to work in the terminal and continues to work in pycharm. I get this error in the terminal :
$ python A_inventory_fetch.py
Traceback (most recent call last):
File "A_inventory_fetch.py", line 58, in <module>
main()
File "A_inventory_fetch.py", line 14, in main
import Scripts.connection_methods.credentials as credentials
ModuleNotFoundError: No module named 'Scripts'Here's the folder structure:
Scripts
βββ Sync_Inventory
β βββ A_inventory_fetch.py
β βββ B_oh_by_variant.py
β βββ C_create_sync_data.py
β βββ D_update_site.py
β βββ E_runsync.py
β βββ __init__.py
βββ __init__.py
βββ connection_methods
β βββ __init__.py
β βββ credentials.py
β βββ client_secrets.json
β βββ api_conn.py
β
βββ requirements.txtWhat did I screw up here?
Edit to add: the end goal is to restore my ability to run E_runsync.py from crontab on a remote server. Somewhere along the road with edits, I screwed something up and now get the "No Module named.. " error
I have a project with this directory structure:
folder1
folder2
main.py
config.py
In main.py, I have import config. When I run it from inside PyCharm, it works fine, but when I run it from the command line with the following command (after cd-ing to folder1):
python folder2\main.py
I get this error:
Traceback (most recent call last):
File "folder2\main.py", line 4, in <module>
import config
ModuleNotFoundError: No module named 'config'How do I fix this? I'm using Python 3.6 on Windows 7
I just realised part of the answer:
in the case where the module executes everything at the top-level, i.e. on import, it's therefore ok to define a dummy "no-op" main function, like so:
# Content of mypkg/myscript.py
print("myscript being executed!")
def main():
pass # Do nothing!
This solution will still force me to add this line to the existing scripts, but I think it's a quick but cautious solution.
No solution if the code is under a if __name__=='__main__' though...
There's some design considerations, but I would recommend using a __main__.py for this.
- it allows all command line invocations to share argument parsing logic
- you don't have to touch the scripts, at all
- it is explicit (no do-nothing functions that exist to trigger import)
- it enables refactoring out any other common stateful logic, since __main__.py is never imported when you import your package
- convention. People expect to find command line invocations in __main__.py.
__main__.py
from pathlib import Path
from runpy import run_path
pkg_dir = Path(__file__).resolve().parent
def execute_script():
script_pth = pkg_dir / "local path to script"
run_path(str(script_pth), run_name="__main__")
Then, you can set your_package.__main__:execute_script as a console script in setup.py/pyproject.toml. You can obviously have as many scripts as you like this way.
I'm using Python 3.6.5 on Windows 10.
When I try to run a script from the command line which imports certain modules, like praw, I get ModuleNotFoundError: No module named 'praw'. However, doing pip install praw or python -m pip install praw gives me a list of Requirement already satisfieds. And when I run the script from IDLE, it goes without a hitch.
This doesn't happen for all modules. I tested a bunch, and the following modules throw an error: praw, gspread, prawcore, openpyxl. These are fine: datetime, sqlite3, time, logging, sys, re, glob, collections. So it looks like the problem is limited to modules outside the standard library.
The problem started after installing PyCharm. A year ago, the same thing happened - I installed PyCharm and couldn't run scripts from the command line anymore. I didn't troubleshoot, just uninstalled PyCharm and that resolved everything. This week, I thought that the program was worth another try and installed it again, but the command line issue came up again and I couldn't fix it. Unfortunately, last year's strategy didn't work: I've removed PyCharm from my laptop, and I rebooted - but the problem persists.
I've googled myself silly, and I can't figure out what's going on. Hope someone can help!