简体   繁体   中英

How to access a docstring from a separate script?

Building a GUI for users to select Python scripts they want to run. Each script has its own docstring explaining inputs and outputs for the script. I want to display that information in the UI once they've highlighted the script, but not selected to run it, and I can't seem to get access to the docstrings from the base program.

ex.

test.py

"""this is a docstring"""
print('hello world')

program.py

index is test.py for this example, but is normally not known because it's whatever the user has selected in the GUI.

# index is test.py
def on_selected(self, index):
    script_path = self.tree_view_model.filePath(index)
    fparse = ast.parse(''.join(open(script_path)))
    self.textBrowser_description.setPlainText(ast.get_docstring(fparse))

Let's the docstring you want to access belongs to the file, file.py .

You can get the docstring by doing the following:

import file
print(file.__doc__)

If you want to get the docstring before you import it then the you could read the file and extract the docstring. Here is an example:

import re


def get_docstring(file)
    with open(file, "r") as f:
        content = f.read()  # read file
        quote = content[0]  # get type of quote
        pattern = re.compile(rf"^{quote}{quote}{quote}[^{quote}]*{quote}{quote}{quote}")  # create docstring pattern
    return re.findall(pattern, content)[0][3:-3]  # return docstring without quotes


print(get_docstring("file.py"))

Note: For this regex to work the docstring will need to be at the very top.

Here's how to get it via importlib . Most of the logic has been put in a function. Note that using importlib does import the script (which causes all its top-level statements to be executed), but the module itself is discarded when the function returns.

If this was the script docstring_test.py in the current directory that I wanted to get the docstring from:

""" this is a multiline
    docstring.
"""
print('hello world')

Here's how to do it:

import importlib.util

def get_docstring(script_name, script_path):
    spec = importlib.util.spec_from_file_location(script_name, script_path)
    foo = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(foo)
    return foo.__doc__

if __name__ == '__main__':

    print(get_docstring('docstring_test', "./docstring_test.py"))

Output:

hello world
 this is a multiline
    docstring.

Update:

Here's how to do it by letting the ast module in the standard library do the parsing which avoids both importing/executing the script as well as trying to parse it yourself with a regex.

This looks more-or-less equivalent to what's in your question, so it's unclear why what you have isn't working for you.

import ast

def get_docstring(script_path):
    with open(script_path, 'r') as file:
        tree = ast.parse(file.read())
        return ast.get_docstring(tree, clean=False)

if __name__ == '__main__':

    print(repr(get_docstring('./docstring_test.py')))

Output:

' this is a multiline\n    docstring.\n'

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