Python 在没有服务器的情况下使用pydoc将模块索引写入文件
目前,我使用以下命令为Python库编写文档:Python 在没有服务器的情况下使用pydoc将模块索引写入文件,python,documentation,pydoc,Python,Documentation,Pydoc,目前,我使用以下命令为Python库编写文档: python -m pydoc -w "\\myserver.com\my_library" 这很好,我在my_库HTML文件中找到了从类/方法/函数docstring派生的文档。这甚至记录了在子文件夹中找到的Python文件 我现在想创建并保存一个索引,它可以访问所有这些文件 pydoc文档说,如果启动服务器,这是可能的: pydoc-b将启动服务器并另外打开一个web浏览器 模块索引页。每个服务页面的顶部都有一个导航栏 在可以获得单个项目帮助
python -m pydoc -w "\\myserver.com\my_library"
这很好,我在my_库
HTML文件中找到了从类/方法/函数docstring派生的文档。这甚至记录了在子文件夹中找到的Python文件
我现在想创建并保存一个索引,它可以访问所有这些文件
pydoc
文档说,如果启动服务器,这是可能的:
pydoc-b将启动服务器并另外打开一个web浏览器
模块索引页。每个服务页面的顶部都有一个导航栏
在可以获得单个项目帮助的地方,使用搜索所有模块
在他们的大纲行中输入关键字,然后转到模块索引,主题
和关键词页面
但是,我希望在没有服务器解决方案的情况下编写一个模块索引页,包括到单个文件文档的相对链接。然后,我可以将索引+单个文件[每个py文件一个]存储在用户可以访问的目录中
这是可能的,还是有更好的方法来解决这个问题
我已经看过Sphinx,但对于我的要求来说,这似乎有些过分。这基本上可以通过运行一个小脚本来实现:
- 导入要记录的模块
- 将文档写入html文件,然后
- 将动态生成index.html的内部函数的输出写入index.html文件
pydoc
模块的内部结构,但相当紧凑:
import pydoc
import importlib
module_list = ['sys']
for m in module_list:
importlib.import_module(m)
pydoc.writedoc(m)
#the monkey patching optionally goes here
with open('index.html','w') as out_file:
out_file.write(pydoc._url_handler('index.html'))
还有一个缺陷是,它还创建了指向所有内置模块的链接,等等。我们没有(我猜也不想)为这些模块生成文档
我们是否可以从创建index.html文件的pydoc.py
复制函数,并将其修改为仅为所需模块添加链接?不幸的是,这并不是直截了当的,因为函数使用一些非局部范围来实现它的一些逻辑
下一个最好的解决方案是对生成此页面的index\u html()
方法进行修补,以便只列出我们的模块
不幸的是,pydoc.\u url\u handler
使用一个本地函数来实现它,而不是类方法。所以从这里开始就有点棘手了
monkey patch有一个解决方案,但它有点像黑客:
在调用\u url\u处理程序之前,我们需要:
- 定义一个补丁版本,该版本只为模块列表中的元素生成链接(使用通过
\uuuuu占位符\uuuu
的迂回,因为模块列表未在函数运行的范围内定义,所以我们需要做一些与函数硬编码相对应的事情,比如)
- 修补
pydoc
模块的源代码,以使用该本地函数而不是最初定义的函数
这是通过以下方式实现的:
import inspect, ast
__placeholder__ = None
#our patched version, needs to have same name and signature as original
def html_index():
"""Module Index page."""
names= __placeholder__
def bltinlink(name):
return '<a href="%s.html">%s</a>' % (name, name)
heading = html.heading(
'<big><big><strong>Index of Modules</strong></big></big>',
'#ffffff', '#7799ee')
contents = html.multicolumn(names, bltinlink)
contents = [heading, '<p>' + html.bigsection(
'Module List', '#ffffff', '#ee77aa', contents)]
contents.append(
'<p align=right><font color="#909090" face="helvetica,'
'arial"><strong>pydoc</strong> by Ka-Ping Yee'
'<ping@lfw.org></font>')
return 'Index of Modules', ''.join(contents)
#get source and replace __placeholder__ with our module_list
s=inspect.getsource(html_index).replace('__placeholder__', str(module_list))
#create abstract syntax tree, and store the actual function definition in l_index
l_index=ast.parse(s).body[0]
#ast.dump(l_index) #check if you want
#now obtain source from unpatched pydoc, generate ast patch it and recompile:
s= inspect.getsource(pydoc)
m = ast.parse(s)
def find_named_el_ind(body, name):
'''find named element in ast body'''
found=False
for i,e in enumerate(body):
if hasattr(e,'name') and e.name == name:
found=True
break
if not found: raise ValueError('not found!')
return i
#find and replace html_index with our patched html_index
i_url_handler = find_named_el_ind(m.body, '_url_handler')
i_html_index = find_named_el_ind(m.body[i_url_handler].body, 'html_index')
m.body[i_url_handler].body[i_html_index] = l_index
#compile and replace module in memory
co = compile(m, '<string>', 'exec')
exec(co, pydoc.__dict__)
#ast.dump(m.body[i_url_handler]) #check ast if you will
导入检查,ast
__占位符\无
#我们的补丁版本,需要有相同的名称和原始签名
def html_index():
“”“模块索引页。”“”
名称=\占位符__
def bltinlink(名称):
返回“”%(名称,名称)
heading=html.heading(
“模块索引”,
"ffffff","7799ee"
contents=html.multicolumn(名称,bltinlink)
contents=[标题,”+html.bigsection(
‘模块列表’、‘ffffff’、‘ee77aa’,目录)]
contents.append(
“pydoc作者:Ka Ping Yee”
'ping@lfw.org')
返回'Index of Modules',''.join(内容)
#获取源代码并用模块列表替换占位符
s=inspect.getsource(html\u索引)。替换(“占位符”,str(模块列表))
#创建抽象语法树,并将实际函数定义存储在l_索引中
l_index=ast.parse.body[0]
#ast.dump(l#u索引)#检查是否需要
#现在从未修补的pydoc获取源代码,生成ast修补程序并重新编译:
s=inspect.getsource(pydoc)
m=ast.parse(s)
def find_named_el_ind(正文,名称):
''在ast正文中查找命名元素''
发现=错误
对于枚举(正文)中的i,e:
如果hasattr(e,'name')和e.name==name:
找到=真
打破
如果未找到:raise VALUERROR('not found!')
返回i
#查找html_索引并将其替换为修补的html_索引
i_url_handler=find_named_el_ind(m.body,“_url_handler”)
i_html_index=find_named_el_ind(m.body[i_url\u handler].body'html_index')
m、 body[i\u url\u handler]。body[i\u html\u index]=l\u index
#编译并替换内存中的模块
co=编译(m,,'exec')
执行官(公司,pydoc.董事会)
#ast.dump(m.body[i_url_handler])#如果愿意,请检查ast
这基本上可以通过运行一个小脚本来实现:
- 导入要记录的模块
- 将文档写入html文件,然后
- 将动态生成index.html的内部函数的输出写入index.html文件
pydoc
模块的内部结构,但相当紧凑:
import pydoc
import importlib
module_list = ['sys']
for m in module_list:
importlib.import_module(m)
pydoc.writedoc(m)
#the monkey patching optionally goes here
with open('index.html','w') as out_file:
out_file.write(pydoc._url_handler('index.html'))
还有一个缺陷是,它还创建了指向所有内置模块的链接,等等。我们没有(我猜也不想)为这些模块生成文档
我们是否可以从创建index.html文件的pydoc.py
复制函数,并将其修改为仅为所需模块添加链接?不幸的是,这并不是直截了当的,因为函数使用一些非局部范围来实现它的一些逻辑
下一个最好的解决方案是对生成此页面的index\u html()
方法进行修补,以便只列出我们的模块
不幸的是pydoc.\u url\u handler
使用