Of cause you are a good python user (I knew it), definently need to create name hierarchy.
suppose "well named" package like below.
setup.py
MANIFEST
src/
__init__.py
a.py
b.py
One/
__init__.py
a.py
b.py
Two/
__init__.py
a.py
b.py
in setup.py,
setup(name="python-library-wellnamed",
packages=["wellnamed", "wellnamed.One", "wellnamed.Two",],
py_modules=[
"a.py",
"b.py",
"One.a",
"One.b",
"Two.a",
"Two.b",
],
)
It looks OK.
Here my question: in src/One/a.py, you need to import src/a.py. What do you do?
in this case Any way, you have to understand how it works.
In this case Any way, you have to find a right way to do it. Thus, understanding setuptools functionality is a sensible choice.
Very first clue is in page 11 of setuptools presentation.
- develop installs a package without moving it into site-packages/
- Paste.egg-link is the poor man's symlink to ~/co/paste
- easy-install.pth also points to ~/co/paste
When using buildbot(some notes in Japanses found here), I hate to use $PYTHONPATH. You can not package it clean. 'Clean' means you do not need to anything else but svn checkout + setup.py. I think it is evil to do something beside it. You are not AUTOMATED build process if you need to set something by hand.
Can you change $PYTHONPATH from setup.py? I do not know how, I do not know it is right thing to do.
On the other hand, I'm very sure that you can use .pth in this case. You can install .pth file with
What is .pth? Look at documentation of site module(JP).
package_data = {'One':['One.pth']}
etc.
It is still half way. You can not test One/a.py during development.
some thing like
/src/One$ python a.py
.pth solution can't handle this propery. It just too global...
So, hacking sys.path is right way. Look at concept code is below.
import sys
sys.path.append(target dir)
ok, now we need find target dir.
first, we must calculate relative thing.
To get absolute path of doing import,
import os
os.path.abspath(__file__)
Be careful, it give you ".pyc" file instead of ".py".
What we want to do is:
in file of src/One/a.py,
type
import relative
relative.imp(dotdot='a', from=__file__)
to import src/a.py
And
type
import relative
relative.imp(dotdot='Two.a', from=__file__)
to import src/Two/a.py
It looks good idea to define "base path for import" for each imp() call.
in this case, src/ is base path for import.
It is very important that keep relative.imp have no side effect on sys.path.
i.e. imp() has to restore sys.path after import of specified module.
import os
import sys
def imp(**kw):
path = os.path.abspath(kw["from"])
module_name = kw["dotdot"]
base_path = xxx(path, module_name)
sys.path.append(base_path)
exec("import %s"%module_name)
sys.path.remove(base_path)
implementing xxx is not so though.
Now, we improve imp().
import relative
relative.imp(from='..', module='Two.a', importer=__file__)
changed arguments and their names. "from" was error prone.
now "from" means "from" of " from xxx import", not "from" file of where you are looking at.
we can use os.path.join to generate base_path. Won't be tough. very good.
0 件のコメント:
コメントを投稿