I have a vaguely defined function of a class Graph of a module I call gt (it is graph-tool). so i declare g = gt.graph() then want to use g.degree_property_map but do not know how. Therefore I want to see where in code g.degree_property_map or in this case just the function, is defined. How can I find that? I'm working on command line on a vm.
Thanks
For reference the library in question is graph-tool - http://projects.skewed.de/graph-tool/
Also I am currently importing it using from graph_tool.all import * . that is of course somewhat of a problem.
You could use inspect.getsource(gt.Graph.degree_property_map). (You have to import inspect.)
Of course, what you pass into getsource() will change depending on how you imported Graph. So if you used from graphtools.all import *, you'd just need to use inspect.getsource(Graph.degree_property_map).
If you open interactive python (type python and hit ENTER on the command line), you should be able to run the command help(<graph's module name>), then, under the FILE section of the help documentation that is generated, you should see the absolute path to the code you are interested in.
For example, I just ran:
import numpy
help(numpy)
# Returned documentation containing:
# FILE
# /usr/lib/python2.7/dist-packages/numpy/__init__.py
Also,
import my_module # A module I just created that contains the "Line" class
help(my_module)
# Returned documentation containing:
# FILE
# /home/<my user name>/Programming/Python/my_module.py
If it is a normal function (not a builtin, ufunc, etc) you can try using the func_code attribute
For example:
>>> inspect.iscode
<function iscode at 0x02EAEF30>
>>> inspect.iscode.func_code
<code object iscode at 02EB2B60, file "C:\Python27\lib\inspect.py", line 209>
Never mind I just did help(graph_tool) and manually jumped through code. Thanks for the help though!
Related
I currently have the problem that I cant use inspect.getsource (OSError: could not get source code) inside code executed through exec().
For example when i feed the following code as a string into exec(code)
import inspect
def sample(p1):
print(p1)
return 1
print(inspect.getsource(sample))
So does anyone know how i could get the source inside the exec()?
I use python 3.8 64 Bit
Thank you for your answers.
Edit: First of all, thanks for the answers and the help to get the right formating for my question, but the function and the inspect.getsource() have to be inside the exec() string.
Regrettably, as I'm sure you've realised, this simply is not possible using exec...but it is possible using exec_module.
If you are not required to use exec specifically, this may work for you:
import tempfile
from importlib import util
import importlib.machinery
raw = """
def sample(p1):
print(p1)
return 1
import inspect
print(inspect.getsource(sample))
"""
# Create a temporary source code file
with tempfile.NamedTemporaryFile(suffix='.py') as tmp:
tmp.write(raw.encode())
tmp.flush()
# Now load that file as a module
spec = util.spec_from_file_location('tmp', tmp.name)
module = util.module_from_spec(spec)
spec.loader.exec_module(module)
# ...or, while the tmp file exists, you can query it externally
import inspect
print(inspect.getsource(module.sample))
The TLDR is, without a source file, it is just flat out not-possible to use getsource to read the source code of a function, because the implementation reads the source code from the file defined in f.__code__.co_filename on the function (read-only, so monkey patching is impossible).
However, if you write the source code to a temporary file, you can load that file as a module (exec_module is practically identical to the effect of exec, you just have to do a few other steps first).
Note: tmp.flush() <-- don't forget this, tmp.write() doesn't write until you flush, and you'll be 'loading' an empty file if you don't flush it first.
If your code is like this:
exec("""\
import inspect
def sample(p1):
print(p1)
return 1
print(inspect.getsource(sample))\
""")
And the exception is OSError: could not get source code then that probably means that inspect.getsource() requires a
file's source to inspect. exec is a dynamic execution of python code so the sample function that's being defined from exec is not on the file's source!
Something like this:
def sample(p1):
print(p1)
return 1
exec("""\
import inspect
print(inspect.getsource(sample))\
""")
would work because the function sample is defined in the source!
Hope that makes sense and answers your question!
~ PanTrakX
I have two Python files, global.py and test_train.py, both sitting in the same folder. I am trying to allow test_train.py to access everything (functions, variables, etc. in global.py). I cannot get it to work. In the same folder is init.py. I have tried import global and have also referenced Source a Python's file from another Python file, but nothing seems to work. Suggestions?
You should change your file (global.py) name, when you import global.py,
the module name global will conflict with python keyword global
import global # global is keyword in python, you should avoid using this name
# so it will occur error
import global_test # this line is OK, if your .py name is global_test
Typically import global should work.
However, if it doesn't work, you should do a check to see if the import is happening successfully.
A print statement at the end of the global.py script should suffice to tell you so.
Otherwise, if the import is working, then you should try changing your code by encapsulating the entire contents of the global.py in a class, and then creating an object of that class in your test_train.py script to call its functions and attributes.
You can also make use of getattr function to call directly from global.py
Essentially, I have two .py files which lie in the same directory. Namely, foo_v02 and bar_v01.
In bar_v01, I want to import a class from foo_v02. However, for the sake of convenience, I want to use the statement from foo import myClass (ignoring the version number). However, as my file isn't called foo, of course python throws an error as there's no file called foo.py.
My Question: Is there a way I can just use from foo import myClass without having to rename my foo_v02.py file?
Note: I already have code which works but it uses from foo_v02 import myClass, so I'm not experiencing a problem as such. Also, I'm asking this question as my foo_xx.py file will undergo frequent editing so there will be multiple versions (so I don't want to have to edit the import statement with every new version). Also, there's only ever going to be one foo_xx.py in the directory as all the previous versions are moved to a different directory once they're outdated.
EDIT:
I've posted an answer for now, but if anyone has a better way, please feel free to post it!
I think the below code maybe works:
import glob
foo = __import__(glob.glob('foo_*.py')[0][:-3])
myClass = foo.myClass
Since the original answer got deleted...
import glob
a = glob.glob('*.py') ## Returns all of the `python` files
b = a[0]
exec('from {} import myClass'.format(b[:-3]))
I'm using exec() (instead of __import__) as I actually want to run the import statement. Also, the import isn't discarded afterwards.
So I've been doing a lot of research and couldn't find a proper answer. I'm quite new to python so sorry if this is a simple question.
So, basically, I'm creating an UI that has a button that should call a function from another .py file. What I did so far is append the file's folder to sys.path and import the .py file as something else. Example, let's say I'm importing myTools.py:
import myTools as mt
Now I can successfully access all functions within myTools via mt.mainFunction() or anything with the mt. prefix.
Now my question:
When I run mt.myFunction() directly it works just fine. Problem is that mainFunction() is another UI that calls different functions at different times. All these functions are on the myTools file.. but Maya won't find them because when they are called within the mainFunction() they don't have the mt prefix.
I mean, I could run those defs on the userSetup.py but it's quite a big code and I wanted to do that the cleanest way :)
Any ideas?
Thanks in advance!
EDIT:
So I just realized is only one function that isn't working. I'm getting this error:
# Error: NameError: file <maya console> line 1: name 'annotationToLocator' is not defined #
Because of that error, I thought that my mainfunction couldn't find any other function on the module.
The actual code where I declare this function:
jobNum = cmds.scriptJob(e=['SelectionChanged', 'annotationToLocator()'])
def annotationToLocator ():
selList = cmds.ls(sl=True)
for item in selList:
if '_ANN' in str(item):
cmds.select(item,d=True)
newItem = str(item).replace('_ANN', '_LOC')
cmds.select(newItem,add=True)
A couple of weird things about this:
1) It works perfectly when I run the code directly.
2) I'm importing the module on the userSetup file.. I'm getting the error above not only when I try to actually run the function that calls this one, but also when Maya starts..
I tried commenting the scriptjob line and now it works just fine, although obviously now I don't have the scriptjob running. I think is some issue with modules and scriptjobs?!
I'm sorry, I know I got off of the original question path here! :)
This sounds like typical python behaviour and should work correctly. Each module has it's own global scope and each function defined in that module will have access to everything defined in that scope.
So in the myTools module each function has access to each other by name, and every function defined in your main module will have access to the mt module object and can get the functions as it's attributes.
You problem stems from using string references to your function. While that works, it only works if they function you're calling by string is in the global python scope -- which usually means it only works in the listener.
The better way to do any maya callbacks is by passing the functions directly to the callback as function objects, not as strings:
import mymodule
cmds.scriptJob(e=('somethingSelected', mymodule.fancyfunction))
Note that mymodule.fancyfunction is passed without parens: you are telling Maya "use this function." If you did it as mymodule.fancyfunction() you'd be telling Maya to use the result of a call to the function , not the function itself.
In Python 2.7, I'm getting
'module' has no attribute
, and/or
'name' is not defined
errors when I try to split up a large python file.
(I have already read similar posts and the Python modules documentation)
Say you have a python file that is structured like this:
<imports>
<50 global variables defined>
<100 lengthy functions that each use most or all of the globals
defined above, and also call each other>
<main() that calls some of the functions and uses the globals>
So I can easily categorize groups of functions together, create a python file for each group, and put them there. The problem is whenever I try to call any of them from the main python file, I get the errors listed above. I think the problem is related to circular dependencies. Since all of the functions rely on the globals, and each other, they are circularly dependent.
If I have main_file.py, group_of_functions_1.py, and group_of_functions_2.py,
main_file.py will have:
import group_of_functions_1.py
import group_of_functions_2.py
and group_of_functions_1.py will have
import main_file.py
import group_of_functions_2.py
and group_of_functions_2.py will have
import main_file.py
import group_of_functions_1.py
Regardless of whether I use "import package_x" or "from package_x import *" the problem remains.
If I take the route of getting rid of the globals, then most of the functions will have 50 parameters they will be passing around which then also need to be returned
What is the right way to clean this up?
(I have already read similar posts and the Python modules documentation)
One of the sources of your errors is likely the following:
import group_of_functions_1.py
import group_of_functions_2.py
When importing, you don't add .py to the end of the module name. Do this instead:
import group_of_functions_1
import group_of_functions_2