9

I saw this SO question and tried using it by creating a .py file with 2 methods and trying to read it.
The file:

def f1(a):
    print "hello", a
    return 1

def f2(a,b):
    print "hello",a,", hello",b

Trying to read it:

>>> r = open('ToParse.py','r')
>>> t = ast.parse(r.read)

Exception thrown:

Traceback (most recent call last):
  File "<interactive input>", line 1, in <module>
  File "C:\Python26\lib\ast.py", line 37, in parse
    return compile(expr, filename, mode, PyCF_ONLY_AST)
TypeError: expected a readable buffer object

What am I doing wrong?
My goal is to get a python module and be able to parse it using Python - expose its classes and methods.

5
  • Why don't you just import it and then inspect it? Commented Mar 20, 2013 at 8:46
  • 1
    Python has better introspection mechanisms than most, dir(), inspect, __dir__, etc. Looks like you are reinventing the wheel. Commented Mar 20, 2013 at 8:53
  • r.read is a method. Surely you meant r or r.read()? Commented Mar 20, 2013 at 8:54
  • I'm not trying to invent the wheel, I'm looking for the best existing wheel :) Commented Mar 20, 2013 at 9:38
  • @BurhanKhalid, @ cdarke Sometimes we can't import a module, because the dependencies aren't there. But we still want to analyse its structure. Commented Mar 21, 2018 at 23:42

4 Answers 4

13

You need to call read. So your line

t = ast.parse(r.read)

Should be

t = ast.parse(r.read())

See here for info on files and here for info on ast.parse

Sign up to request clarification or add additional context in comments.

Comments

6

If you want to expose your classes and methods dynamically, then you probably need to use eval along with compile.

In this case you may do it like the following.

Create a file:

#test.py
def hello():
    print "hello"

And you can call it like this:

#main.py
testContent = open("test.py").read()
#evaluate a content
eval(compile(testContent, "<string>", 'exec'))
#call function
hello() #prints hello

EDIT: there is another way to evaluate file:

#main.py
#evaluate a content
eval(compile("import test", "<string>", 'exec')) #test.py
#check list of methods
dir(test) # ['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'hello']
#call function
hello() #prints hello

I do realize, that eval may be not that good choice, but I don't know other way. I'd glad to see other solution

3 Comments

agree. but in some particular cases its usage is suitable
I just tried it and PythonWin didn't recognize my methods. Any chance I can get a list out of compile(), of modules and functions (I also need to show them, not just be able to call them)?
compile and ast.parse are similar in this case. Try with ast.parse directly. Otherwise you can always import the code directly and use dir().
4

Use:

t = ast.parse(r.read()) # () is needed

Source: http://docs.python.org/2/tutorial/inputoutput.html#methods-of-file-objects

Comments

2

You are trying to parse the function read on the file.

You want

t = ast.parse(r.read())

or (to more closely follow the example)

text = r.read()
ast.parse(text)

not

t = ast.parse(r.read)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.