I imported a module as below:
filename = "email"
mymodule = __import__('actions.'+filename)
the problem I have with this is, that the file is immediatly executing, and I would much rather execute a specific function from the file (that way I can send variables through it).
I am basically working with plugins, so it works.
Edit:
for the time being, I am not concerned with whether or not the script executes when I add the line below:
mymodule = __import__('actions.'+filename)
but what I would like to work is when I add the line below, I would like the function to execute. But instead I get an error that the module dosn't have that function even though it exisits in the script.
mymodule.dosomething(n)
Edit:
I personally don't think that the function has anything to do with it but here is one python files that I am trying to open.
import webbrowser
def OpenEmail():
handle = webbrowser.get()
handle.open('http://gmail.google.com')
OpenEmail()
print "Your email has been opened"
The functions don't exist unless the module executes. You can't have it both ways. Perhaps you need to add a main stanza to the module.
The problem is, that you get the actions module returned. Try this:
mymodule = __import__('actions.'+filename)
for submodule in filename.split('.'):
mymodule = getattr(mymodule, submodule)
This happens when you try importing a submodule, i.e. module.something.somethingelse, you get module returned.
Related
I want to be able to get the path to the file which is importing my python library. How can I do that?
For example:
The user creates a file at C:\Users\Bob\bobsproject\main.py. From within the library, I want to be able to get the path to the file, and read it as a txt. How can I do that?
If you want to get the name of the driver script that is (possibly indirectly) loading your library, you can use the fact that python runs a script under the name __main__. You can get it from sys.modules just like any other module and access its __file__ attribute if it exists:
import sys
try:
print(sys.modules['__main__'].__file__)
except KeyError:
print('libray not loaded from script')
except AttributeError:
print('script not loaded from file')
The KeyError is unlikely to ever occur (not even if you run the script with python -m), but it's useful to be safe. The AttributeError is much more likely, and can easily be demonstrated with something like python -c.
If you want something more complex, like the file containing the code that actually called your library function, you will likely have to use the inspect module or similar. This will be even less robust as a matter of course, but may still suit your needs:
import inspect
module = inspect.getmodule(inspect.stack()[1][0])
try:
print(module.__file__)
except AttributeError:
print(f'module "{module.__name__}" not loaded from file')
Notice that inspect.getmodule explicitly uses the word "guess" in its official documentation, while inspect.stack can be a fidgety beast sometimes.
Code for second part referenced from here: https://stackoverflow.com/a/1095621/2988730.
Remember that there are two options here. If you place this code directly in your library module, it will be executed exactly once, when the module is first imported. If you place it in a function that the user can call directly, you will see the printouts every time. If you place the second snippet it in a utility function that you then call from your public module functions, don't forget to increment the frame index to reflect that:
module = inspect.getmodule(inspect.stack()[2][0])
I'm new to python and doing an assignment. It's meant to be done with linux but as I'm doing it by myself on my own computer I'm doing it on windows.
I've been trying to do this test system that we use looking like this:
>>> import file
>>> file.function(x)
"Answer that we want"
Then we run it through the linux terminal. I've been trying to create my own way of doing this by making a test file which imports the file and runs the function. But then on the other hand of just running the function it runs the whole script. Even though it's never been called to do that.
Import file
file.function(x)
That's pretty much what I've been doing but it runs the whole "file". I've also tried from file import function; it does the same.
What kind of script can I use to script the "answer that I want" for the testfile? As when we run in through linux terminal it says if it has failed or scored.
importing a file is equivalent to running it.
When you import a file (module), a new module object is created, and upon executing the module, every new identifier is put into the object as an attribute.
So if you don't want the module to do anything upon importing, rewrite it so it only has assignments and function definitions.
If you want it to run something only when invoked directly, you can do
A = whatever
def b():
...
if __name__ == '__main__'
# write code to be executed only on direct execution, but not on import
# This is because direct execution assigns `'__main__'` to `__name__` while import of any way assigns the name under which it is imported.
This holds no matter if you do import module or from module import function, as these do the same. Only the final assignment is different:
import module does:
Check sys.modules, and if the module name isn't contained there, import it.
Assign the identifier module to the module object.
from module import function does
Check sys.modules, and if the module name isn't contained there, import it. (Same step as above).
Assign the identifier function to the module object's attribute function.
You can check if the module is imported or executed with the __name__ attribute. If the script is executed the attribute is '__main__'.
It is also good style to define a main function that contains the code that should be executed.
def main()
# do something
pass
if __name__ == '__main__'
main()
When writing throwaway scripts it's often needed to load a configuration file, image, or some such thing from the same directory as the script. Preferably this should continue to work correctly regardless of the directory the script is executed from, so we may not want to simply rely on the current working directory.
Something like this works fine if defined within the same file you're using it from:
from os.path import abspath, dirname, join
def prepend_script_directory(s):
here = dirname(abspath(__file__))
return join(here, s)
It's not desirable to copy-paste or rewrite this same function into every module, but there's a problem: if you move it into a separate library, and import as a function, __file__ is now referencing some other module and the results are incorrect.
We could perhaps use this instead, but it seems like the sys.argv may not be reliable either.
def prepend_script_directory(s):
here = dirname(abspath(sys.argv[0]))
return join(here, s)
How to write prepend_script_directory robustly and correctly?
I would personally just os.chdir into the script's directory whenever I execute it. It is just:
import os
os.chdir(os.path.split(__file__)[0])
However if you did want to refactor this thing into a library, you are in essence wanting a function that is aware of its caller's state. You thus have to make it
prepend_script_directory(__file__, blah)
If you just wanted to write
prepend_script_directory(blah)
you'd have to do cpython-specific tricks with stack frames:
import inspect
def getCallerModule():
# gets globals of module called from, and prints out __file__ global
print(inspect.currentframe().f_back.f_globals['__file__'])
I think the reason it doesn't smell right is that $PYTHONPATH (or sys.path) is the proper general mechanism to use.
You want pkg_resources
import pkg_resources
foo_fname = pkg_resources.resource_filename(__name__, "foo.txt")
I'm new to python and doing an assignment. It's meant to be done with linux but as I'm doing it by myself on my own computer I'm doing it on windows.
I've been trying to do this test system that we use looking like this:
>>> import file
>>> file.function(x)
"Answer that we want"
Then we run it through the linux terminal. I've been trying to create my own way of doing this by making a test file which imports the file and runs the function. But then on the other hand of just running the function it runs the whole script. Even though it's never been called to do that.
Import file
file.function(x)
That's pretty much what I've been doing but it runs the whole "file". I've also tried from file import function; it does the same.
What kind of script can I use to script the "answer that I want" for the testfile? As when we run in through linux terminal it says if it has failed or scored.
importing a file is equivalent to running it.
When you import a file (module), a new module object is created, and upon executing the module, every new identifier is put into the object as an attribute.
So if you don't want the module to do anything upon importing, rewrite it so it only has assignments and function definitions.
If you want it to run something only when invoked directly, you can do
A = whatever
def b():
...
if __name__ == '__main__'
# write code to be executed only on direct execution, but not on import
# This is because direct execution assigns `'__main__'` to `__name__` while import of any way assigns the name under which it is imported.
This holds no matter if you do import module or from module import function, as these do the same. Only the final assignment is different:
import module does:
Check sys.modules, and if the module name isn't contained there, import it.
Assign the identifier module to the module object.
from module import function does
Check sys.modules, and if the module name isn't contained there, import it. (Same step as above).
Assign the identifier function to the module object's attribute function.
You can check if the module is imported or executed with the __name__ attribute. If the script is executed the attribute is '__main__'.
It is also good style to define a main function that contains the code that should be executed.
def main()
# do something
pass
if __name__ == '__main__'
main()
Note: Solved. It turned out that I was importing a previous version of the same module.
It is easy to find similar topics on StackOverflow, where someone ran into a NameError. But most of the questions deal with specific modules and the solution is often to update the module.
In my case, I am trying to import a function from a module that I wrote myself. The module is named InfraPy, and it is definitely on sys.path. One particular function (called listToText) in InfraPy returns a NameError, but only when I try to import it into another script. Inside InfraPy, under if __name__=='__main__':, the listToText function works just fine. From InfraPy I can import other functions with no problems. Including from InfraPy import * in my script does not return any errors until I try to use the listToText function.
How can this occur?
How can importing one particular function return a NameError, while importing all the other functions in the same module works fine?
Using python 2.6 on MacOSX 10.6, also encountered the same error running the script on Windows 7, using IronPython 2.6 for .NET 4.0
Thanks.
If there are other details you think would be helpful in solving this, I'd be happy to provide them.
As requested, here is the function definition inside of InfraPy:
def listToText(inputList, folder=None, outputName='list.txt'):
'''
Creates a text file from a list (with each list item on a separate line). May be placed in any given folder, but will otherwise be created in the working directory of the python interpreter.
'''
fname = outputName
if folder != None:
fname = folder+'/'+fname
f = open(fname, 'w')
for file in inputList:
f.write(file+'\n')
f.close()
This function is defined above and outside of if __name__=='__main__':
I've tried moving InfraPy around in relation to the script. The most baffling situation is that when InfraPy is in the same folder as the script, and I import using from InfraPy import listToText, I receive this error: NameError: name listToText is not defined. Again, the other functions import fine, they are all defined outside of if __name__=='__main__': in InfraPy.
This could happen if the module has __all__ defined
Alternatively there could be another version of the module in your path that is getting imported instead of the one you are expecting
Is the NameError about listToText or is it something inside the function causing the exception?
In addition the __all__ variable gnibbler mentioned you could also have a problem with a InfraPy.pyc file lying around somewhere.
I'd recommend putting a import pdb;pdb.set_trace() first in the InfraPy.py file to make sure you are in the right file, and step through the definition of InfraPy.py to see what is happening. If you don't get a breakpoint, you are importing another file than you think.
You can also dir(InfraPy) after importing it, and check which file you are actually importing with InfraPy.__file__.
Can't think of any more import debugging hints right now. ;-)