Very basic Python project structure fails - python

I have the following project:
apack/
apack/
__init__.py
apack.py
aux.py
setup.py
apack.py:
def foo(x):
return x
aux.py:
from apack import foo
def bar():
return foo() + 1
setup.py:
from setuptools import setup, find_packages
setup(
name='apack',
packages=find_packages()
)
I install the package with pip install .. However, the result is a an empty package:
>>> import apack
>>> apack.foo
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: module 'apack' has no attribute 'foo'
What I would like to have is:
>>> import apack
>>> apack.foo()
>>> apack.bar()
There is a number of similar questions here (e.g., 1, 2). However, none of them is minimal enough for me to understand why my example does not work.

When you import the package it invokes the __init__ file of the package. You can confirm this in your python interpreter.
>>> import json
>>> json.__file__
'<PATH>\\lib\\json\\__init__.py'
So to have foo and bar available from your package level you have to import foo and bar into the __init__ file of your package. ie,
from .apack import foo
from .aux import bar

Related

Why is the behaviour of commands in __init__.py in python packages different from command line?

Python Newbie.
I am trying to create a python package. The file structure is -
+-demo1
+-nsdemo
+- __init__.py
+- bar.py
The contents of bar.py are
bar_var = 'abc'
The contents of __ init __.py are
print('this is nsdemo')
from nsdemo import bar
After adding the path in sys.path, I tried to access bar or bar_var after import nsdemo, but the following error occured:
>>> import nsdemo
this is nsdemo
>>> bar
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'bar' is not defined
but when I did the same from command line:
>>> import nsdemo
this is nsdemo
>>> from nsdemo import bar
>>> bar
<module 'nsdemo.bar' from 'demo1/nsdemo/bar.py'>
>>> bar.bar_var
'abc'
If the code in __init__.py is supposed to run when I import the package, why won't it run the way same as the command line?

What does 'from dot import asterisk' do in Python 3?

Question
What does the following line do in Python 3?
>>> from . import *
What I found out so far...
It does not output anything and the only change I can see in Python 3.7.3 is the following:
>>> '__warningregistry__' in locals()
False
>>> from . import *
>>> '__warningregistry__' in locals()
True
>>> locals()['__warningregistry__']
{'version': 0}
This might be part of the warnings module and indicates that there is a warning somewhere which is not printed, but the documentation mentions only a variable __warningregistry__ in the the module warnings.
The documentation explains how from . import foo works, and how from bar import * works, but I couldn't find anything about from . import *. One might expect that all names from __init__.py are loaded into the current name space (as from bla import * would do for bla.py) but this doesn't seem to be the case and also it doesn't make sense when __name__ == '__main__' (scripts and terminal).
Python 2 behaves more similar to what I had expected:
>>> # Python 2.7.16
>>> from . import *
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: Attempted relative import in non-package
PEP 328 is quite illuminative but doesn't answer my question either.
When __main__ is a script or interactive session, . is the __main__ package itself:
$ python3 -c 'from . import float'
Traceback (most recent call last):
File "<string>", line 1, in <module>
ImportError: cannot import name 'float' from '__main__' (unknown location)
This makes from . import * a noop, with __warningregistry__ added as a side-effect of the import machinery.
Relative imports from __main__ were special-cased by PEP 366. This introduced __package__ for relative package name lookup, and specifies that __main__. __package__ has the special value None.
In addition, the module import spec __main__.__spec__ may be None - namely in an interactive shell or when executing a script.
As it turns out, any module with __package__ = __spec__ = None will treat . as itself:
$ cat test.py
__package__ = __spec__ = None
from . import float
$ python3 -c 'import test'
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/Users/mfischer/PycharmProjects/lispy/test.py", line 2, in <module>
from . import float
ImportError: cannot import name 'float' from 'test' (./test.py)
The __warningregistry__ is added because there is a hidden warning from the missing attributes. It is suppressed by default, but you can see it with all warning enabled:
$ python3 -Wa -c 'from . import float'
-c:1: ImportWarning: can't resolve package from __spec__ or __package__, falling back on __name__ and __path__
Traceback (most recent call last):
File "<string>", line 1, in <module>
ImportError: cannot import name 'float' from '__main__' (unknown location)

importing my own python modules

I have written a small python module called phpcs. I
folder structure
cs_qa_support
phpcs
init.py
config_file.py
setup.py
contents of setup.py
from setuptools import setup
setup(name='cs_qa_support',
version='0.1',
description='QA Support',
packages=['phpcs'],
zip_safe=False)
I installed this using the command
pip install -e .
the file phpcs/init.py is empty
the content of phpcs/confif_file is
class PhpcsConfigFile:
def __init__(self,configFileName):
self.__config_file_name = configFileName
def dump(self):
print self.__config_file_name
given all of that I want to start using the module
my first attempt
>>> import phpcs
>>> config_file.PhpcsConfigFile
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'config_file' is not defined
second attempt
>>> from phpcs import config_file
>>> config_file.PhpcsConfigFile
<class phpcs.config_file.PhpcsConfigFile at 0x7fe5ef4b7738>
My question is can I avoid typing config_file.PhpcsConfigFile and just use PhpcsConfigFile?
Thanks
you can do it like this
from phpcs import config file as con
then do this
con.phpcsConfifFile

Why can `__init__.py` import a submodule but a test file with `from module import *` can't?

I have the following folder structure.
project/
sandbox.py
module/
__init__.py
klass.py
__init__.py has the following:
from klass import Klass
if __name__ == '__main__':
'do stuff'
This works fine. sandbox.py looks like this:
from module import *
if __name__ == '__main__":
'do similar stuff'
On the command line, while in the project directory:
$ python module/__init__.py
# things work correctly
$ python sandbox.py
Traceback (most recent call last):
File "sandbox.py", line 1, in <module>
from module import *
File "/Uses/chuck/.../project/module/__init__.py, line 1 in <module>
from klass import Klass
ImportError: No module named 'klass'
I think this might have to do with relative imports, and tried changing from klass import Klass to from .klass import Klass, but that didn't work either.
My goal is, from files outside the module, to be able to use from module import * or from module import Klass. What do I need to do?
In case it matters, this is with Python 3.5.2 under macOS within a virtual environment.
Use absolute path and __main__.py file for this:
from module.klass import Klass
'do stuff'
In __init__.py:
from .klass import Klass
Now you can execute it as follows:
$ python sandbox.py
do similar stuff
$ python -m module
do somthing

python absolute import of submodule fails

I have seen other posts but did not find answer that worked!
File structure
my_package/
__init__.py -- empty
test/
__init__.py -- empty
test1.py
Fail
from my_package import test
test.test1
gives
AttributeError: 'module' object has no attribute test
Following Passes
from my_package.test import test1
# or
import my_package.test.test1
from my_package import test
# now this works
test.tes1
<module 'my_package.test.test1' from ...
I have
from __future__ import absolute_import
in all files, and using python2.7
When you import a package (like test), the modules (like test1) are not automatically imported (unless perhaps you put some special code to do so in __init__.py). This is different from importing a module, where the contents of the module are available in the modules namespace. Compare with the Python standard library's xml.etree.ElementTree module:
>>> import xml
>>> xml.etree
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'etree'
>>> from xml import etree
>>> etree.ElementTree
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'ElementTree'
>>> from xml.etree import ElementTree
>>> ElementTree.ElementTree
<class 'xml.etree.ElementTree.ElementTree'>

Categories

Resources