I am using import DiGraph to import my external file and trying to run the following code:
prediction = DiGraph.remove_duplicates(make_trips(G, source='c1', target=['c2', 'c3']))
but I get NameError: name 'make_trips' is not defined
All the names are how they appear in my external file and it is even identical code besides the prediction =. What am I missing?
*Edit:
Thanks, Gilch, Kartikeya Sharma, and Nishat for the explanations.
Did you mean DiGraph.make_trips?
Importing like that only gives you the one module object; it doesn't dump its contents into the current namespace. (You could use from DiGraph import * for that, but star imports get confusing fast, so they're generally not recommended.)
Now I get NameError: name 'G' is not defined. 'G' is a variable at the top of the file. How should I handle this? Thanks
At the top of the DiGraph file? You can do it the same way. DiGraph.G.
If DiGraph is too much to type, you can do
import DiGraph as dg
instead of import DiGraph. Then you can refer to the DiGraph module as dg instead, e.g.
prediction = dg.remove_duplicates(dg.make_trips(dg.G, source='c1', target=['c2', 'c3']))
you can import your external function like this
from <module> import <function>
So if your make_trip function is inside make_trip.py file then you can import like this
from make_trip import make_trip
Related
I have a fairly extensive coding background in multiple environments, but, am new to Python. I thought I had figured out a way to import functions dynamically from an external '.py' file, but am unsure if it is the best way. I found problems with using importlib.import_module() and importlib.__import__ based on my goal. Is there another way to accomplish what I am doing here? Effectively, I am wanting to have the same result as I would get when using from x import y where x and y are variables. I thought I would be able to use eval('from '+x+' import '+y) but this throws a syntax error.
I was hoping to accomplish this by contriving a dictionary with files as the keys (i.e., a file named 'file1.py' would create a key of 'file1') and a list of the desired functions as a list associated with its relative key. This can easily be built either literally, or by reading a path for file names and then using the dir() function to get a list of the functions in each individual file (among many other ways). Next, I hoped to simply use nested for loops to walk the dictionary keys and their associated key value lists and used eval('from '+key+' import '+currentListItem). Unfortunately, this throws a syntax error on the execution of the generated 'from...import...' statement. See below for example code. My problems with importlib (and getattr) is that I am unable to maintain the 'abstraction' provided by this method as I have to define a 'handle' in order to use importlib (i.e., handle = getattr(...) or handle = importlib.import_module(key) meaning that I basically have to hard code a 'handle name' for the given module being imported and thus may just as well hard code the 'from file_name import function' statements).
# simplistic example of what I was thinking....
# FILE file.py contains the code...
def asub(p1, p2 = None, p3 = None):
print(p1, p2 if p2 else 'p2 defaulted', p3 if p3 else 'p3 defaulted')
return
# FILE b.py contains the code...
#!/usr/local/bin/python3
subs = {'file':['asub']}
for key in subs:
for subrt in subs[key]:
print("==>", key, subrt)
eval('from '+key+' import '+subrt)
# on execution of b.py (i.e., ```python3 b.py``` I get the following...
Traceback (most recent call last):
File "b.py", line 9, in <module>
eval('from '+key+' import '+subrt)
File "<string>", line 1
from file import asub
^
SyntaxError: invalid syntax
NOTE: I understand that this may not be the greatest thing for importing modules/functions as it tends to 'hide' the information that you would need for documentation and usage of the imported functions.
However, I am sure that there will be instances where this may be useful or where similar methodology may be useful in a case other than importing.
As I said, I am new to Python, so, am looking for feedback/guidance on this in a (cringe) 'Pythonic' sense.
One other thing: I get that eval() can open the door for code insertion but for the above specific use, and given that the files containing the functions are well locked down, I think it should be plenty safe (?)...
Thanks in advance for any feedback
Try this:
from importlib.machinery import SourceFileLoader
subs = {'file':['asub']}
for key in subs:
# import module by file path
# since path is relative, it will import against working directory
mod = SourceFileLoader("", "%s.py" % key).load_module()
for subrt in subs[key]:
print("==>", key, subrt)
# retrieve object from module by name subrt
obj = getattr(mod, subrt)
# this should call file.asub and it does
obj('1', '2')
# this add local variable with the same name
locals()[subrt] = obj
# so now we can call asub as if it were done
# from file import asub
asub('3', '4')
This code prints:
==> file asub
1 2 p3 defaulted
3 4 p3 defaulted
This works on my python3 and requires python 3.3 at least. This is built on top of question How to import a module given the full path?. locals()[subrt] = obj puts imported object into local variables directory, which allows calling to it as if it were done from file import asub. If i understood correctly this is what you wanted to achieve?
FYI, Final form based on accepted answer provided by Radoslaw. NOTE: I also tested with importlib.import_module(key) as well and that worked the same way except that you may have to use sys.path.insert(...) to make sure your module can be located.
import os, sys, re
from importlib.machinery import SourceFileLoader
# Build list of 'things' to be imported
# (presumably via a lookup of some sort)
# I hard coded it here as a simple dictionary element for testing/dev.
# Notice that a fully qualified file name is used so that the target
# subroutine/function can come from any specified/discovered file
# Another option may be to use only a list of file names here and then # use 'dir()' to get the functions from the file and then choose from
# the the list returned. This is illustrated below.
subs = {'/some/fully/qualified/path/file.txt':['asub']}
# import the files
for key in subs:
mod = SourceFileLoader("", key).load_module()
# Example of how to 'extract' the function names from the module for
# filtering and loading of explicit modules when using 'subs' as a
# list vs. a dictionary. Here I simply excluded anything beginning
# and ending with double '_' and then processed those 'functions'.
# for d in dir(mod):
# if not re.match(r'^__.+?__$', d):
# locals()[subrt] = getattr(mod, subrt)
# otherwise, if 'subs' is used as a dictionary as
# described above, just walk the list of functions
# built as part of the 'subs' dictionary
for subrt in subs[key]:
locals()[subrt] = getattr(mod, subrt)
# done
asub('parm1', 'p2_parm')
quit()
An interesting exercise. Thanks much for the help Radoslaw.
I'm trying to import a class from another script so I can run the class when a button is clicked in tkinter.
The line of code I'm trying to run is:
from tkinter import *
import originalscript as desiredclass
variable = desiredclass()
When I try to run my code, the second line gives me an 'invalid syntax' error.
The two files are in the same folder and I've looked at other threads regarding this problem, but most of them suggest this as the solution, however, this line is not working for me, so I'm wondering what I am doing wrong/what I am missing?
The error code is:
Syntax Error: invalid syntax: filepath.py, line 2, pos 10
import script as class
UPDATE:
from you update to your question it looks like you may be trying to import the file as a class. Instead of doing:
variable = desiredclass()
Try this:
variable = desiredclass.ClassNameInFile()
There are several ways you might wish to import your own files.
For example if your file structure looks like this:
--Workfolder
--Main.py
--other.py
You may want to import something like this.
import other
Or if you want only something specific from that file do:
from other import func_name
However if it is part of a package you sometimes need to specify the package name first.
So if your file structure is like this:
--Workfolder
--MY_PACKAGE
--Main.py
--other.py
You may want to import like this:
import MY_PACKAGE.other
or for a specific function:
from MY_PACKAGE.other import func_name
Let me know if you have any questions.
I fetched a cristal structure of a protein using the function retrieve_pdb_file from Bio.PDB. The default format has changed from PDB to PDBx/mmCif. I want to extract the protein sequence from the header in the cif file. There is supposed to be a simple function in Bio.PDB called MMCIF2Dict to do this but the module is not callable. I also downloaded the cif file manually and put it in the script folder but still the same error. My biopython is up to date. Am I doing something wrong or the module is not well implemented? Thank you for your answers.
from Bio.PDB import *
cifFile = '1bu7.cif'
mmcif = MMCIF2Dict(cifFile)
TypeError: 'module' object is not callable
The module is well implemented. The problem with your code is that you are calling a module instead of a function. In your particular case the module and the function have the same names hence the confusion.
To solve that you need to fix your code as follows:
from Bio.PDB import *
cifFile = '1bu7.cif'
mmcif = MMCIF2Dict.MMCIF2Dict(cifFile)
Try:
from Bio.PDB.MMCIF2Dict import MMCIF2Dict
Instead of :
from Bio.PDB import *
So I am having trouble importing classes in the same directory and getting them to work properly.
I currently have the following hiearchy
BBDriver.py
bbsource:
BouncyBallEnv.py
Console.py
resources:
misc:
objects:
Ball.py
Platform.py
My problem is between the 2 files in the bbsource directory. I have figured out how to get access from the bbsource directory down to the classes in the objects directory and vice versa but when I try to from BouncyBallEnv import BouncyBallEnv in the Console class I get the following error:
File "E:\PycharmProjects\BouncyBallPythonV0\bbsource\Console.py", line 5, in
from BouncyBallENV import BouncyBallEnv
ImportError: cannot import name 'BouncyBallEnv'
I have tried several things like:
from bbsource import BouncyBallEnv
from bbsource.BouncyBallEnv import BouncyBallEnv
But I can't get it to work.
The only time I could get it to work is when I did the following:
import bbsource.BouncyBallEnv
#Extra
print(bbsource.BouncyBallEnv.BouncyBallEnv.WIDTH)
But there must be a better way to do it than that so that I wouldn't have to type that lengthy statement that is in the print statement every time that I want to use a static variable in BouncyBallEnv.
I am still quite confused on how the Python importing works so I'm not sure how to go about doing this. Thank you.
NOTE: Running Python 3.5.1
the thing you need is aliases :
import bbsource.BouncyBallEnv as bbe
#Extra
print(bbe.WIDTH)
and you can't import a module with the from ... import ... syntax. Only attributes. It work like this :
import <module> [as <alias>]
or
from <module> import <attribute> [, <attribute2>...] # import some attributes
from <module> import * # import everything
with the second one, you could have done :
from bbsource.BouncyBallEnv import WIDTH
# the variable WIDTH is directly loaded : watch out for collision !
print(WIDTH)
It is abosolue_import rule.
try
from .BouncyBallENV import BouncyBallEnv
to access module in relative position.
besides, there should be an __init__.py file under bbsource directory
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!