Can distutils create empty __init__.py files? - python

If all of my __init__.py files are empty, do I have to store them into version control, or is there a way to make distutils create empty __init__.py files during installation?

In Python, __init__.py files actually have a meaning! They mean that the folder they are in is a Python module. As such, they have a real role in your code and should most probably be stored in Version Control.
You could well imagine a folder in your source tree that is NOT a Python module, for example a folder containing only resources (e.g. images) and no code. That folder would not need to have a __init__.py file in it. Now how do you make the difference between folders where distutils should create those files and folders where it should not ?

Is there a reason you want to avoid putting empty __init__.py files in version control? If you do this you won't be able to import your packages from the source directory wihout first running distutils.
If you really want to, I suppose you can create __init__.py in setup.py. It has to be before running distutils.setup, so setup itself is able to find your packages:
from distutils import setup
import os
for path in [my_package_directories]:
filename = os.path.join(pagh, '__init__.py')
if not os.path.exists(filename):
init = open(filename, 'w')
init.close()
setup(
...
)
but... what would you gain from this, compared to having the empty __init__.py files there in the first place?

Related

Irerate over package_data files and copy them to current working directory

Background
I'm developing a python package with roughly the following directory structure:
mossutils/
setup.py
mossutils/
__init__.py
init.py
data/
style.css
script.js
...
My package's setup.py declares console_scripts and includes package_data files:
setup(
name='mossutils',
packages=['mossutils'],
package_data={"mossutils": ["data/*"]},
entry_points = {
"console_scripts": ['mu-init = mossutils.init:main']
},
...)
Installing the package via pip install works as expected: everything is installed in my Python's Lib\site-packages, including the data directory and all files in it, and script mu-init can be executed from the shell (or rather, command prompt, since I'm using Windows).
Goal
Script mu-init is supposed to do some kind of project scaffolding in the current working directory it is invoked from. In particular, it should copy all package_data files (data/style.css, data/script.js, ...) to the current directory.
Solution Attempt
Using module pkgutil, I can read the content of a file, e.g.
import pkgutil
...
data = pkgutil.get_data(__name__, "data/style.css")
Questions
Is there a way for my init.py script to iterate over the contents of the data directory, without hard-coding the file names (in init.py)?
Can the files from the data directory be copied to the current working directory, without opening the source file, reading the content, and writing it to a destination file?
You can get the list of files in the directory using pkg_resources library, which is distributed together with setuptools.
import pkg_resources
pkg_resources.resource_listdir("mossutils", "data")

Is __init__.py required for every python package? [new feature since python 3.3+]

I have see this in python tutorial:
The __init__.py files are required to make Python treat the directories as containing packages;
I make the directory hierarchy in pycharm like this, where the subdir1 doesn't contain __init__.py and subdir2 contains a __init__.py file.
First, I add Directory into system.pyth.
I write a hello function in hello1.py and hello2.py respectively.
Then I call hello func in test files like this:
# test1.py
from subdir1 import hello1
hello1.hello()
# test2.py
from subdir2 import hello2
hello2.hello()
They all succeed. It seems that the __init__.py does not necessary for import modules from different directories, right?
So, I want to know in what situation a __init__.py is required. Thanks for your answering!
Python 3.3+ has implicit namespace packages that allow you to create packages without __init__.py. In Python 2, __init__.py is the old method and still works.
Allowing implicit namespace packages means that the requirement to provide an __init__.py file can be dropped completely, and affected portions can be installed into a common directory or split across multiple directories as distributions see fit.
Note: init.py files were used to mark directories on your disk as Python packages.
Useful links:
Implicit Namespace Packages
__init__.py
All the code in the Python interpreter will be lost when we exit the interpreter. But when writing large programs file is broken into multiple different files for ease of use, debugging and readability. In Python modules are used to achieve such goals. Modules are nothing but files with Python definitions and statements. The module name, to import, has the same name of the Python file without the .py extension.
So if you want the files under some directory to be a module and you want it to be a exportable module into some other piece of code then that category need to have the init.py
More details
For making Python treat the Directory as a package.
Python Doc

Expanding sys.path via __init__.py

There're a lot of threads on importing modules from sibling directories, and majority recommends to either simply add init.py to source tree, or modify sys.path from inside those init files.
Suppose I have following project structure:
project_root/
__init__.py
wrappers/
__init__.py
wrapper1.py
wrapper2.py
samples/
__init__.py
sample1.py
sample2.py
All init.py files contain code which inserts absolute path to project_root/ directory into the sys.path. I get "No module names x", no matter how I'm trying to import wrapperX modules into sampleX. And when I try to print sys.path from sampleX, it appears that it does not contain path to project_root.
So how do I use init.py correctly to set up project environment variables?
Do not run sampleX.py directly, execute as module instead:
# (in project root directory)
python -m samples.sample1
This way you do not need to fiddle with sys.path at all (which is generally discouraged). It also makes it much easier to use the samples/ package as a library later on.
Oh, and init.py is not run because it only gets run/imported (which is more or less the same thing) if you import the samples package, not if you run an individual file as script.

Add a folder to the Python library path, once for all (Windows)

I use
sys.path.append('D:/my_library_folder/')
import mymodule
in order to import some module.
How to add permanently this folder D:/my_library_folder/ to the Python library path, so that I will be able to use only
import mymodule
in the future?
(Even after a reboot, etc.)
just put the folder in site-packages directory. ie:
C:\PythonXY\Lib\site-packages
Note: you need to add an empty file __init__.py to the folder
Files named __init__.py are used to mark directories on disk as a Python package directories.
If you have the files:
C:\PythonXY\Lib\site-packages\<my_library_folder>\__init__.py
C:\PythonXY\Lib\site-packages\<my_library_folder>\module.py
you can import the code in module.py as:
from <my_library_folder> import module
If you remove the __init__.py file, Python will no longer look for submodules inside that directory, so attempts to import the module will fail.
If you have lots of folders, then create the empty __init__.py file in each folder. for eg:
C:\PythonXY\Lib\site-packages\<my_library_folder>\
__init__.py
module.py
subpackage\
__init__.py
submodule1.py
submodule2.py
Set PYTHONPATH environment variable to D:/my_library_folder/
If D:/my_library_folder is a project you're working on and has a setup script, you could also do python setup.py develop. Not entirely related to the question, but I also recommend using virtualenv.

Import Python Issues

I've been writing in python for a couple of months now and I've never found a through explanation of how import works. I downloaded this folder with subfolders with python files in them. I'm trying to use one of these files and I'm loosing my mind. How do you properlly import a folder with all the files in it?
Any help would be greatly appreciated.
As written in the python documentation on modules:
If you have a folder sound looking like that :
sound/ Top-level package
__init__.py Initialize the sound package
effects/ Subpackage for sound effects
__init__.py
echo.py
surround.py
reverse.py
To import all files of effects folder :
from sound.effects import *
Note that to be able to import module, they have to contain an __init__.py file.
First, check to see if the subdirectories have a file named __init__.py file in them. Python will not recognize directories that do not contain these files.
Then, you will have to manually change the PYTHONPATH, which you can find in sys.path. You can find a great example here.
Edit: I'm not 100% sure this is what you were asking for. If you want to import ALL the python files in a directory, you will have to import them one by one. For example, given a directory like so:
parent/
__init__.py
runner.py
example.py
language.py
you would have to type
from parent import runner, example, language
or
from parent import * # this will also import __init__
You have to create a __init__.py file in the directory to make it a package. In this file you import all the symbols from the underlying files.
See http://docs.python.org/tutorial/modules.html (especially part 6.4 Packages) for further notes on that.
The parent folder must be either in PYTHONPATH or the folder path indicated in a file with extension .pth situated in a location in your path, usually in site-packages.
Then your package and all folders inside it from which you have to import need to have a file named __init__. This file can be used for program initialization but as a starting point it can be an empty file.
For example my program folder, situated in C:\python26 has the estructure:
programas\
.....package1\
.........__init__.py
.........module1.py
.........subpackage1\
.............__init__.py
.............module2.py
.....package2\
.........__init__.py
.........module3
.....__init__.py
.....lonelyscript1.py
.....lonelyscript2.py
file site-packages\site.pth contains:
C:\Python26\programas

Categories