简体   繁体   中英

Can pydoc operate on a pyd, or is there an equivalent to pydoc that operates on a pyd

It seems to me that pydoc only works on py source code files.

Can it be used on a compiled pyd file in some way? The error I get in attempting that is

ValueError: source code string cannot contain null bytes

which arises, obviously, due to the fact that the compiled pyd contains NUL bytes.

Looking at the pydoc library, specially its source code (3.9) , the function importfile works with .py and .pyc , but does not with .pyo nor .pyd files.

It may be possible to write custom code to parse the content of a .pyd file and re-use parts of pydoc to generate the documentation, but I think it is not simple.

Another way is through the builtin help that calls pydoc . here is a proof of concept :

# file: main.py
"""
Hello pydoc !
"""
# file: setup.py
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext

ext_modules = [
    Extension("main",  ["main.py"]),
]

setup(
    name='My pyd file',
    cmdclass={'build_ext': build_ext},
    ext_modules=ext_modules
)

(I have installed Cython in my venv, so that I can compile .py files into .pyd )

I run python setup.py build_ext --inplace which produces the main.cp36-win_amd64.pyd file.
I move this file into another directory (to not mess the import later), and I use this file :

# file: get_pydoc.py
import main

if __name__ == "__main__":
    help(main)

which is in the same directory than the .pyd file (and nothing else). When ran, it prints :

Help on module main:

NAME
    main - Hello pydoc !

DATA
    __test__ = {}

FILE
    c:\\pycharmprojects\stack_overflow\q68002833_check\main.cp36-win_amd64.pyd

which proves it is possible.

Looking at the CPython implementation for help as of 3.9 we can see it only does return pydoc.help(*args, **kwds) . So we can call pydoc directly :

# file: get_pydoc.py
import pydoc

import main

if __name__ == "__main__":
    pydoc.help(main)

and still have the same output.

But it prints its output directly on stdout, which is not convenient. Looking at its Cpython 3.9 implementation that it uses by default its output field, which is a property ( see here ) that returns sys.stdout if no output has been provided to the constructor, which is the case for the default Helper .

So by constructing a new Helper object whose output is an in-memory io.StringIO , we have the following code :

# file: get_pydoc.py
import io
import pydoc

import main

if __name__ == "__main__":
    doc_content = io.StringIO()
    helper = pydoc.Helper(output=doc_content)
    helper.help(main)
    print(doc_content.getvalue())

I think it answers your question : you can write a script that will get the pydoc from a .pyd file. It is just not as straightforward, because it is very less common.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM