如何访问Python包中的顶级文件代码
我有一个Python 2.7的包,结构是这样的:
hdl/
__init__.py
run_job.py
other_stuff/
__init__.py
other_files/
setup.py
scripts/
client.py
run_job.py
文件里面包含:
def run_job():
pass
这里没有任何类。其实,这个代码库里根本没有类;我是继承过来的。
我该如何从这个包的客户端执行run_job()
函数呢?
(现在,run_job()
函数在__init__.py
里,我对此一点也不喜欢。)
我在__init__.py
里放了这些:
import hdl.run_job
import run_job
无论如何,我都收到了No module named run_job
的错误。如果我完全不导入,客户端代码会显示'module' object has no attribute 'run_job'
或者name 'run_job' is not defined
,这取决于我做了哪一步:
import hdl
hdl.run_job
import hdl
run_job
我的setup.py
文件:
from setuptools import setup
from setuptools import find_packages
from os import walk, path
install_requires = [
"ecdsa==0.11",
"importlib==1.0.3",
"paramiko==1.13.0",
"pyasn1==0.1.7",
"pycrypto==2.6.1",
"wsgiref==0.1.2",
]
script_base = "scripts"
my_path = path.dirname(path.abspath(__file__))
walk_path = path.join(my_path, script_base)
for(_, _, filenames) in walk(walk_path):
scripts = [("%s/%s" % (script_base, f)) for f in filenames]
break
setup(
name="hdl",
version="dev",
description="HDL",
url="http://example.com",
long_description="HDLA",
author="heh",
author_email=".com",
maintainer="foo",
maintainer_email=".com",
license="Proprietary",
packages=find_packages(exclude=("tests",)),
test_suite="nose.collector",
include_package_data=True,
package_data = {'': [ '*.csv', '*.hql', '*.pig', '*.sh', '*.sql' ]},
install_requires=install_requires,
zip_safe=False,
classifiers=[
"Development Status :: 2 - Alpha",
"Environment :: Command Line",
"Framework :: None",
"Intended Audience :: Developers",
"Intended Audience :: System Administrators",
"License :: Other/Proprietary License",
"Natural Language :: English",
"Operating System :: MacOS :: MacOS X",
"Operating System :: POSIX :: Linux",
"Programming Language :: Python :: 2.7",
"Topic :: Software Development",
"Topic :: ETL"
],
scripts=scripts,
)
如果我把run_job
函数放在__init__.py
里,它就能正常工作:
import hdl
hdl.run_job()
3 个回答
这个文件的名字不是 run_job.py
,而是其他的名字。唉。把名字改对了,所有东西就能正常工作了。
其他的回答都是对的;把 __init__.py
留空,然后在 client.py
里这样写:
from hdl import run_job
run_job.run_job()
或者
from hdl.run_job import run_job
run_job()
或者把这个放在 __init__.py
里:
from .run_job import run_job
然后在 client.py
里写这个:
import hdl
hdl.run_job() # won't work
你的客户端代码需要先写 from hdl import run_job
,然后再调用 run_job.run_job()
,或者(可能更容易理解)写 from hdl.run_job import run_job
。
如果你想让用户可以直接使用 run_job
,也就是说不需要先导入 run_job
模块就能使用这个函数,那么在你的顶层文件 __init__.py
中写 from .run_job import run_job
。这样用户就可以直接写 import hdl
,然后使用 hdl.run_job
。
把下面的内容放到 __init__.py
文件里:
__all__ = ["run_job"]
在你的客户端代码里:
from hdl import run_job
run_job.run_job()
在你的 setup.py 文件中,"scripts" 这个变量没有定义,所以我把下面这行去掉了:
scripts=scripts,
之后我运行了 "sudo python setup.py install",然后用客户端测试了一下:
$ python
Python 2.7.6 (default, Mar 22 2014, 17:40:27)
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from hdl import run_job
>>> run_job.run_job()
>>>
一切正常。
再试试别的事情:
pydoc hdl
检查一下生成的文档中提供的路径是否指向正确的位置。
Help on package hdl:
NAME
hdl
FILE
<path-to-hdl>/hdl/__init__.py
PACKAGE CONTENTS
run_job
所以,我的文件结构和你的完全一样,setup.py 文件内容也一样。下面是文件的内容,在我的电脑上可以正常工作。仔细对比一下你这边的,确保 "setup.py install" 没有任何错误。如果 pydoc 没有显示任何内容,说明 hdl 没有安装成功。
==========
run_job.py
===========
def run_job():
pass
============ client.py ===========
from hdl import run_job
run_job.run_job()
============ setup.py ===========
和你的完全一样