I'm trying to find the first function in arbitrary Python code.
What's the best way to do this?
Here's what I've tried so far.
import ast
import compiler.ast
code = """\
def func1():
return 1
def func2():
return 2
"""
tree = compiler.parse(code)
print list(ast.walk(tree))
But I'm getting an error I don't understand.
Traceback (most recent call last):
File "test.py", line 15, in <module>
print list(ast.walk(tree))
File "/usr/lib64/python2.7/ast.py", line 215, in walk
todo.extend(iter_child_nodes(node))
File "/usr/lib64/python2.7/ast.py", line 180, in iter_child_nodes
for name, field in iter_fields(node):
File "/usr/lib64/python2.7/ast.py", line 168, in iter_fields
for field in node._fields:
AttributeError: Module instance has no attribute '_fields'
Use ast.parse, not compiler.parse:
>>> import ast
>>>
>>> code = """
... def func1():
... return 1
...
... def func2():
... return 2
... """
>>>
>>> tree = ast.parse(code)
>>> [x.name for x in ast.walk(tree) if isinstance(x, ast.FunctionDef)]
['func1', 'func2']
What about this, please let me know if that works:
import ast
import compiler.ast
code = """\
def func1():
return 1
def func2():
return 2
"""
n = compiler.parse(code).getChildNodes()
print n[0].nodes[0].name
Related
I want to use the reactome2py package to analyse pathways by adapting the Reference code. Unlike the reference code, which only read one file, my code intends to apply the reactome2py's analysis function for three files, mrna, cna, and meth.
Reference code:
https://colab.research.google.com/drive/1OufIYapCWirfLsudpg0fw1OxD7KTud2y?usp=sharing#scrollTo=e1q6oxLUKGGR
The portion of the code that's throwing the error:
for k, v in chain.from_iterable(cna_dict_items):
cna_dd[k].extend(v)
Full code:
import pandas as pd
import numpy as np
from sklearn.decomposition import PCA
from operator import methodcaller
from itertools import chain
from collections import defaultdict
from reactome2py import analysis
directory = "./gbm_tcga/"
def genepath(cna_row_dict):
cna_dd = defaultdict(list)
cna_dict_items = map(methodcaller("items"), cna_row_dict)
for k, v in chain.from_iterable(cna_dict_items):
cna_dd[k].extend(v)
cna_dict = dict(cna_dd)
return cna_dict
class DataProcessing:
def __init__(self, data):
self.df = pd.read_csv(data, sep="\t", header=0)
def data_dict(self):
df_dict = self.df.to_dict("records")
return df_dict
def main():
cna = DataProcessing(directory + "data_linear_cna.txt")
cna_dict = cna.data_dict()
gene_path = genepath(cna_dict)
main()
Traceback:
Traceback (most recent call last):
File "main.py", line 45, in <module>
main()
File "main.py", line 41, in main
gene_path = genepath(cna_dict)
File "main.py", line 19, in genepath
cna_dd[k].extend(v)
TypeError: 'float' object is not iterable
I'm making a program that uses derivates to calculate an error.
I keep getting this error : 'Mul' object has no attribute 'sp'.
The solutions to this error that i've found so far are when people import everything from sympy and math (from sympy/math import *) because both sympy and math have a sin() function.
But as you can see from my code bellow i don't have it like that and the error still shows up, why?
import sympy as sp
from math import factorial
def F(x):
return 4*(x**2)+sp.sin(9*x)
sp.init_printing()
x=sp.symbols('x')
def D1(x1):
return(sp.diff(F(x),x,1).sp.subs(x,x1))
def D2(x1):
return(sp.diff(F(x),x,2).sp.subs(x,x1))
def D3(x1):
return(sp.diff(F(x),x,3).sp.subs(x,x1))
def maxD3(x1,x2):
if(D3(x1)>D3(x2)):
return D3(x1)
else:
return D3(x2)
erro1 = (1/factorial(3))*maxD3(-1,1)*abs((0.3-(-1))*(0.3-1))
erro1 = (1/factorial(3))*maxD3(-1,1)*abs((0.83-(-1))*(0.83-1))
print("Erro f(0.3): ", erro1)
print("Erro f(0.83): ", erro2)
Also have changed "from math import factorial" to "import math as math" and the error also keeps showing up.
I'm using Python 3.6.1.
EDIT: Full Traceback
Traceback (most recent call last):
File "main.py", line 24, in <module>
erro1 = (1/math.factorial(3))*maxD3(-1,1)*abs((0.3-(-1))*(0.3-1))
File "main.py", line 19, in maxD3
if(D3(x1)>D3(x2)):
File "main.py", line 16, in D3
return(sp.diff(F(x),x,3).sp.subs(x,x1))
AttributeError: 'Mul' object has no attribute 'sp'
This is the corrected version of your code
import sympy as sp
from math import factorial
def F(x):
return 4*(x**2)+sp.sin(9*x)
sp.init_printing()
x=sp.symbols('x')
def D1(x1):
return(sp.diff(F(x),x,1).subs(x,x1)) # subs instead of sp.subs
def D2(x1):
return(sp.diff(F(x),x,2).subs(x,x1)) # subs instead of sp.subs
def D3(x1):
return(sp.diff(F(x),x,3).sp.subs(x,x1))
def maxD3(x1,x2):
if(D3(x1)>D3(x2)):
return D3(x1)
else:
return D3(x2)
erro1 = (1/factorial(3))*maxD3(-1,1)*abs((0.3-(-1))*(0.3-1))
erro2 = (1/factorial(3))*maxD3(-1,1)*abs((0.83-(-1))*(0.83-1)) # erro2 instead of erro1
print("Erro f(0.3): ", erro1)
print("Erro f(0.83): ", erro2)
Output on my system:
('Erro f(0.83): ', 0)
('Erro f(0.83): ', 0)
Is this the expected output?
Also, you don't need to import everything from sympy. You can just import what you need.
Example:
>>> from sympy import sin, symbols, diff
>>> x = symbols('x')
>>> f = x**3 + sin(x)
>>> print(diff(f, x))
3*x**2 + cos(x)
>>> print(diff(f, x).subs(x, 1))
cos(1) + 3
I want to check a string - is it an import command? I have tried
# Helper - analyses a string - is it an import string?
"""
fromlike - from foo import bar
classic - import foo
classic_as - import foo as baz
"""
def check_is_import(string):
importname = ''
fromlike = False
classic = False
classic_as = False
if string[0:4] is 'from':
fromlike = True
importname = ''
if not fromlike and (string[0:6] is 'import'):
classic = True
importname = string.split(' ')[1]
if classic:
commandlist = string.split(' ')
if commandlist[2] is 'as':
classic_as = True
importname = commandlist[3]
del commandlist
if fromlike:
return ('fromlike', importname)
elif classic and (not classic_as):
return ('classic', importname)
elif classic_as:
return ('classic_as', importname)
else:
return ('no_import', importname)
but it worked for "fromlike" imports. (Note: I'm not asking "why does this code don't work?", I'm just searching a solution) What code will sure detect all imports? Basically my code takes a slice of the string. If the [0:4] slice equals 'from', the string is a "fromlike import". Else: if the [0:6] slice equals 'import', the string is a "classic import". If it detects 'as', it will find the pseudo-name. This function must return a tuple which contains the import type under index 0 and imported module-name under index 1.
If you want to be sure to handle all Python import forms, have Python do the parsing. Use the ast.parse() function and use the resulting parse tree; you'll either get Import or ImportFrom objects:
| Import(alias* names)
| ImportFrom(identifier? module, alias* names, int? level)
Each alias consists of a name and optional identifier used to import the name as:
-- import name with optional 'as' alias.
alias = (identifier name, identifier? asname)
Note that there can be multiple imports! You either have classic or fromlike imports, and both can import multiple names. Your function needs to return a list of (type, name) tuples. For invalid inputs, raise an exception (ValueError is a good fit here):
import ast
def check_is_import(string):
try:
body = ast.parse(string).body
except SyntaxError:
# not valid Python
raise ValueError('No import found')
if len(body) > 1:
# not a single statement
raise ValueError('Multiple statements found')
if not isinstance(body[0], (ast.Import, ast.ImportFrom)):
raise ValueError('No import found')
type_ = 'classic' if isinstance(body[0], ast.Import) else 'fromlike'
results = []
for alias in body[0].names:
alias_type = type_
if alias.asname:
alias_type += '_as'
results.append((alias_type, alias.asname or alias.name))
return results
The method should probably be renamed to extract_import_names(), as that reflects what it does much better.
Demo:
>>> check_is_import('from foo import bar')
[('fromlike', 'bar')]
>>> check_is_import('import foo')
[('classic', 'foo')]
>>> check_is_import('import foo as baz')
[('classic_as', 'baz')]
>>> check_is_import('from foo import bar, baz as spam, monty as python')
[('fromlike', 'bar'), ('fromlike_as', 'spam'), ('fromlike_as', 'python')]
>>> check_is_import('import foo as baz, baz, spam as ham')
[('classic_as', 'baz'), ('classic', 'baz'), ('classic_as', 'ham')]
>>> check_is_import('invalid python')
Traceback (most recent call last):
File "<stdin>", line 3, in check_is_import
File "/Users/mjpieters/Development/Library/buildout.python/parts/opt/lib/python3.6/ast.py", line 35, in parse
return compile(source, filename, mode, PyCF_ONLY_AST)
File "<unknown>", line 1
invalid python
^
SyntaxError: invalid syntax
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 6, in check_is_import
ValueError: No import found
>>> check_is_import('import foo; import bar')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 9, in check_is_import
ValueError: Multiple statements found
>>> check_is_import('1 + 1 == 2')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 11, in check_is_import
ValueError: No import found
def h(x):
x = ((x[0])*len(x))
return x
when i print it, it goes
h(he)
Traceback (most recent call last):
File "<pyshell#45>", line 1, in <module>
h(he)
NameError: name 'he' is not defined
Do you maybe mean to pass he as a string? 'he' would be the appropriate way then.
def h(x):
x = ((x[0])*len(x))
return x
print(h('he'))
>>> hh
I am working with a o.o.p and trying to use pickle to load a list of lines I save in a .txt file. I can save the data with pickle, but I am not sure why it can't see 'painter' after I have initialized it.
class LoadButton(MTButton):
def __init__(self, **kwargs):
super(LoadButton, self).__init__(**kwargs)
self.buttonLoad = kwargs.get('painter')
def on_release(self, touch):
if touch.device != 'wm_pen':
newLoad = self.buttonLoad
loadFile = open('savefiles/savetest.txt', 'rb')
newpainter = painter
scatter.remove_widget(painter) # if removed error: EOF, no data read
# error: local var 'painter' referenced before assignment
oldlines = pickle.load(loadFile)
painter = newpainter
scatter.add_widget(painter)
pprint.pprint(oldlines)
loadFile.close()
return True
Any help would be awesome. Thanks.
It is because painter = newpainter creates a local variable painter, even if after the part when you call the global painter.
Do something like this:
painter_ = newpainter
scatter.add_widget(painter_)
EDIT: But why don't you use only painter?
scatter.remove_widget(painter)
oldlines = pickle.load(loadFile)
scatter.add_widget(painter)
EDIT 2:
Example:
>>> bar = 'Bar'
>>> def foo():
... bar # This is the local bar. It has not been assigned a value yet.
... bar = 'Local Bar' # Here I assign a value to the bar.
...
>>> foo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in foo
UnboundLocalError: local variable 'bar' referenced before assignment
>>>