Python: cannot load class from my module - python

EDIT:
I couldn't use my own modules. It was a stupid waste of time. If you ever have the same problem, try reading this first:
http://docs.python-guide.org/en/latest/writing/structure/
I just started OOP with Python and I am confused by modules and classes.
I work with a Mac and I can write my own modules and load them from the site-packages folder.
Now I would like to create modules with useful classes.
import custom_module works.
But if custom_module has a class Custom_class, things don't work.
I tried doing:
(EDIT: I am sorry, I am removing old code which was made up, this is what I just used and doesn't work)
in custommodule.py:
class Customclass:
def __init__(self, name):
self.name = name
This module loads without errors.
Then I get:
new = custommodule.Customclass('foo')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'Customclass'
BTW, I started trying to do this using code from this tutorial
I was not able to get over this. Please advise, I must be doing something wrong.

With this file layout
site-packages/custommodule/__init__.py
site-packages/custommodule/custommodule.py
you are creating a package named custommodule that contains a module also named custommodule. Your code needs to look like
import custommodule
# or more specifically,
# import custommodule.custommodule
new = custommodule.custommodule.Customclass('foo')
or
from custommmodule import custommodule
new = custommodule.Customclass('foo')
You can also put custommodule.py directly in site-packages to avoid creating the package, in which case your original code should work.

For me, at least, this works from mod_name import ClassName
When I run this code I don't get any errors. Hope this helped
EDIT: also make sure that the module you want to import is in the project directory. If you view the left panel in the images both modules are in Stack. I hope this is obvious but, the class needs to be in the module you import as well. Make sure that the class you're importing does not import the class your importing in because then you get circular dependencies.

Try this way
File custommodule.py in the directory custommodule
class Customclass:
def __init__(self, name):
self.name = name
File __init__.py int he custommodule directory
from .custommodule import CustomClass
Note the dot before custommodule. This force the init to load the module from the same directory.
Without the dot, it work under python2 but not under python3

Related

Import class from another file

I know this question has been asked before, but none of the given answers worked. Say I have a file named Test.py with this code:
class Test():
def __init__(self):
print('Instance Created')
I want to use this class in another file, say Test2.py.
I used the path to the file to get the class, but the message attempted relative import with no known parent package pops up
.
I am using IDLE on Mac OS X.
The path to the file is /Users/*name*/Desktop/Code/Test.py, where *name* is my username for this device.
Code in Test2.py:
from .Users.*name*.Desktop.Code.Test import Test
When I run the program, this message comes up:
Traceback (most recent call last):
File "/Users/*name*/Desktop/Code/Test2.py", line 1, in <module>
from .Users.owen.Desktop.Code.Test import Test
ImportError: attempted relative import with no known parent package
I have tried using sys.path.append but it doesn't seem to work. I have also tried using just .Desktop or .Code instead of the full name, but this gives the same error. I researched packages online, but am struggling to fully comprehend what they are, much less make/use them. Any help would be greatly appreciated.

Using a class whose methods are decorated by #ray.remote in another directory

I'm learning how to use the python package Ray to parallel my code. I'm facing a problem with a class whose methods are decorated with #ray.remote.
It is okay for me to import the class in the same folder and execute the method in the class. However, after importing the class to another directory, it raises ModuleNotFoundError when the method is called.
According to the trackback of the error, it seems like the issue is about the deserialization process when the program can not find the module it requires.
A minimal working example of my issue is shown below.
Structure of the directory.
folder/
main/
a_class.py
process_in_main.py
processing/
process_not_in_main.py
Content of three scripts
# a_class.py
import ray
class Foo:
#ray.remote
def single_function(self):
return None
def combined_function(self):
ray.init()
results_id = [Foo.single_function.remote(self) for i in range(5)]
results = ray.get(results_id)
ray.shutdown()
return None
# process_in_main.py, it works fine
import a_class
instance = a_class.Foo()
instance.combined_function()
# process_not_in_main.py
import sys
sys.path.append('../')
from main import a_class
instance = a_class.Foo()
instance.combined_function() # it will raise ModuleNotFoundError: No module named 'main'
Any help would be appreciated. Thanks in advance.
Please check that the imports are really resolvable. Both scripts work for me, when I set the Pythonpath to the parent of folder and use absolute imports that start with "folder".
Dockerised example here (since I´m at windows at the moment) :
https://github.com/FelixKleineBoesing/stackoverflowSnippets/tree/master/question59809169

using import inside class

I am completely new to the python class concept. After searching for a solution for some days, I hope I will get help here:
I want a python class where I import a function and use it there. The main code should be able to call the function from the class. for that I have two files in the same folder.
Thanks to #cdarke, #DeepSpace and #MosesKoledoye, I edited the mistake, but sadly that wasn't it.
I still get the Error:
test 0
Traceback (most recent call last):
File "run.py", line 3, in <module>
foo.doit()
File "/Users/ls/Documents/Entwicklung/RaspberryPi/test/test.py", line 8, in doit
self.timer(5)
File "/Users/ls/Documents/Entwicklung/RaspberryPi/test/test.py", line 6, in timer
zeit.sleep(2)
NameError: global name 'zeit' is not defined
#wombatz got the right tip:
it must be self.zeit.sleep(2) or Test.zeit.sleep(2). the import could be also done above the class declaration.
Test.Py
class Test:
import time as zeit
def timer(self, count):
for i in range(count):
print("test "+str(i))
self.zeit.sleep(2) <-- self is importent, otherwise, move the import above the class declaration
def doit(self):
self.timer(5)
and
run.py
from test import Test
foo = Test()
foo.doit()
when I try to python run.py I get this error:
test 0
Traceback (most recent call last):
File "run.py", line 3, in <module>
foo.doit()
File "/Users/ls/Documents/Entwicklung/RaspberryPi/test/test.py", line 8, in doit
self.timer(5)
File "/Users/ls/Documents/Entwicklung/RaspberryPi/test/test.py", line 6, in timer
sleep(2)
NameError: global name 'sleep' is not defined
What I understand from the error is that the import in the class is not recognized. But how can I achive that the import in the class is recognized?
Everything defined inside the namespace of a class has to be accessed from that class. That holds for methods, variables, nested classes and everything else including modules.
If you really want to import a module inside a class you must access it from that class:
class Test:
import time as zeit
def timer(self):
self.zeit.sleep(2)
# or Test.zeit.sleep(2)
But why would you import the module inside the class anyway? I can't think of a use case for that despite from wanting it to put into that namespace.
You really should move the import to the top of the module. Then you can call zeit.sleep(2) inside the class without prefixing self or Test.
Also you should not use non-english identifiers like zeit. People who only speak english should be able to read your code.
sleep is not a python builtin, and the name as is, does not reference any object. So Python has rightly raised a NameEror.
You intend to:
import time as zeit
zeit.sleep(2)
And move import time as zeit to the top of the module.
The time module aliased as zeit is probably not appearing in your module's global symbol table because it was imported inside a class.
You want time.sleep. You can also use;
from time import sleep
Edit: Importing within class scope issues explained here.
You're almost there! sleep is a function within the time module. This means that the name sleep doesn't exist unless its understood within the context of time, unless you define it on your own. Since you didn't define it on your own, you can access it by running time.sleep(2).
In your specific example, you used:
import time as zeit
you'll have to run:
zeit.sleep(2)
Alternatively, you can import sleep directly from time, by running:
from time import sleep
sleep(2)
Good luck!
You can read more about the time module here: https://docs.python.org/2/library/time.html
You can learn more about imports here: https://docs.python.org/3/reference/import.html
and I highly recommend learning about namespace in python, here: https://bytebaker.com/2008/07/30/python-namespaces/
I agree with #Wombatz on his solution, but I do not have enough reputation to comment on his question
One use case that I have found for importing a module within a class is when I want to initialize a class from a config file.
Say my config file is
config.py
__all__ = ['logfile', ... ]
logfile = 'myevent.log'
...
And in my main module
do_something.py
class event():
from config import *
def __init__(self):
try : self.logfile
except NameError: self.logfile = './generic_event.log'
Now the advantage of this scheme is that we do not need to import logfile in the global namespace if it is not needed
Whereas, importing at the beginning of do_something.py, I will have to use globals inside the class, which is a little ugly in my opinion.
It's probably a bit late, but I agree with idea of not polluting the module-level namespace (of course this can probably be remedied with a better design of a module, plus 'explicit is better than implicit' anyways).
Here is what I would do. The basic idea is this: import is an implicit assignment in which an entire module object gets assigned to a single name. Thus:
class Test:
import time as zeit
self.zeit = zeit # This line binds the module object to an attribute of an instance created from the class
def timer(self, count):
for i in range(count):
print("test "+str(i))
self.zeit.sleep(2) # This necessitates the `zeit` attribute within the instance created from the class
def doit(self):
self.timer(5)
import importlib
class importery():
def __init__(self, y,z):
self.my_name = y
self.pathy = z
self.spec = importlib.util.spec_from_file_location(self.my_name, self.pathy)
x = importlib.util.module_from_spec(self.spec)
self.spec.loader.exec_module(x)
print(dir(x))
root = x.Tk()
root.mainloop()
pathy = r'C:\Users\mine\Desktop\python310\Lib\tkinter\__init__.py'
importery('tk', pathy)
There is a 'time and a place' to do this type of black magic, thankfully very rare times and places. Of the few I've found I've normally been able to use subprocess to get some other flavor of python to do my dirty work, but that is not always an option.
Now, I have 'used' this in blender when I've needed to have conflicting versions of a module loaded at the same time. This is not a good way to do things and really should be a last resort.
If you are a blender user and you happen to decide to commit this sin, I suggest doing so in a clean version of blender, install a like version of python next to it to use that to do your pip installs with, and please make sure you have added your config folder to your blender folder, else this black magic may come back to bite you in the arse later.

Python import error: 'module' object has no attribute 'x'

I am trying to do a python script that it is divided in multiple files, so I can maintain it more easily instead of making a very-long single file script.
Here is the directory structure:
wmlxgettext.py
<pywmlx>
|- __init__.py
|- (some other .py files)
|- <state>
|- __init__.py
|- state.py
|- machine.py
|- lua_idle.py
if I reach the main directory of my project (where the wmlxgettext.py script is stored) and if I try to "import pywmlx" I have an import error (Attribute Error: 'module' object has no attribute 'state')
Here is the complete error message:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/user/programmi/my/python/wmlxgettext/true/pywmlx/__init__.py", line 9, in <module>
import pywmlx.state as statemachine
File "/home/user/programmi/my/python/wmlxgettext/true/pywmlx/state/__init__.py", line 1, in <module>
from pywmlx.state.machine import setup
File "/home/user/programmi/my/python/wmlxgettext/true/pywmlx/state/machine.py", line 2, in <module>
from pywmlx.state.lua_idle import setup_luastates
File "/home/user/programmi/my/python/wmlxgettext/true/pywmlx/state/lua_idle.py", line 3, in <module>
import pywmlx.state.machine as statemachine
AttributeError: 'module' object has no attribute 'state'
Since I am in the "project main directory" pywmlx should be on PYTHONPATH (infact I have no troubles when I tried to import pywmlx/something.py)
I'm not able to figure where is my error and how to solve this problem.
Here is the pywmlx/__init__.py source:
# all following imports works well:
from pywmlx.wmlerr import ansi_setEnabled
from pywmlx.wmlerr import wmlerr
from pywmlx.wmlerr import wmlwarn
from pywmlx.postring import PoCommentedString
from pywmlx.postring import WmlNodeSentence
from pywmlx.postring import WmlNode
# this is the import that does not work:
import pywmlx.state as statemachine
Here is the pywmlx/state/__init__.py source:
from pywmlx.state.machine import setup
from pywmlx.state.machine import run
But I think that the real problem is somewhat hidden in the "imports" used by one (or all) python modules stored in pywmlx/state directory.
Here is the pywmlx/state/machine.py source:
# State is a "virtual" class
from pywmlx.state.state import State
from pywmlx.state.lua_idle import setup_luastates
import pywmlx.nodemanip as nodemanip
def addstate(self, name, value):
# code is not important for this question
pass
def setup():
setup_luastates()
def run(self, *, filebuf, fileref, fileno, startstate, waitwml=True):
# to do
pass
Finally here is the pywmlx/state/lua_idle.py source:
import re
import pywmlx.state.machine as statemachine
# State is a "virtual" class
from pywmlx.state.state import State
# every state is a subclass of State
# all proprieties were defined originally on the base State class:
# self.regex and self.iffail were "None"
# the body of "run" function was only "pass"
class LuaIdleState (State):
def __init__(self):
self.regex = re.compile(r'--.*?\s*#textdomain\s+(\S+)', re.I)
self.iffail = 'lua_checkpo'
def run(xline, match):
statemachine._currentdomain = match.group(1)
xline = None
return (xline, 'lua_idle')
def setup_luastates():
statemachine.addstate('lua_idle', LuaIdleState)
Sorry if I posted so much code and so many files... but I fear that the files, in directory, hides more than a single import problem, so I published them all, hoping that I could explain the problem avoiding confusion.
I think that I miss something about how import works in python, so I hope this question can be useful also to other programmers, becouse I think I am not the only one who found the official documentation very difficult to understand when explaining import.
Searches Done:
Not Useful: I am already explicitly using import x.y.z all times I need to import something
Not Useful: Even if the question asks about import errors, it seems not useful for the same reason as (1)
Not Useful: As far as I know, pywmlx should be located into PYTHONPATH since "current working directory" on my tests is the directory that contains the main python script and pywmlx directory. Correct me if I am wrong
Python does several things when importing packages:
Create an object in sys.modules for the package, with the name as key: 'pywmlx', 'pywmlx.state', 'pywmlx.state.machine', etc.
Run the bytecode loaded for that module; this may create more modules.
Once a module is fully loaded and it is located inside another package, set the module as an attribute of the parent module object. Thus the sys.modules['pywmlx.state'] module is set as the state attribute on the sys.modules['pywmlx'] module object.
That last step hasn't taken place yet in your example, but the following line only works when it has been set:
import pywmlx.state.machine as statemachine
because this looks up both state and machine as attributes first. Use this syntax instead:
from pywmlx.state import machine as statemachine
Alternatively, just use
import pywmlx.state.machine
and replace statemachine. everywhere else with pywmlx.state.machine.. This works because all that is added to your namespace is a reference to the sys.modules['pywmlx'] module object and the attribute references won't need to be resolved until you use that reference in the functions and methods.
You are having a circular import in your framework. Circular imports do not work well with aliases. When importing a module with an alias and then, during the circular import, importing it again without an alias, python complains. The solution is to not use aliases (the "import module as" syntax) but always use the full "import module" statement.

eclipse,python, NameError: name <MyModule> is not defined

I create the following package in eclipse via PyDev:
class Repository(object):
'''
classdocs
'''
def __init__(self):
'''
Constructor
'''
print("salaam")
class Materials(Repository):
'''
'''
def __init__(self):
'''
constructor
'''
My main file is:
if __name__ == '__main__':
pass
import repository;
x = Repository();
When i run my application, i get the following error:
x = Repository();
NameError: name 'Repository' is not defined
Of course, i got a warning on importing my module.
I know my import and relation of my main file and my package or eclipse configuration have problem.
first of all, when you import like this, you can only refer to your class as either repository.Repository or repository.repository.Repository, depending on the whether you import the module or the package.
second, what you import depends on where eclipse thinks you are. You can check that with
import os
print(os.pwd)
at the top of your main script.
third, if you want to import your package like this, you should put it in your search path. You can do that by placing it in site-packages, or for instance by adding
import sys
import os
sys.path.append(os.path.abspath(__file__))
at the top of your main script
additionally, you might want to avoid confusion by giving your module a different name than the package (or the other way round)
(and a little nitpick: __init__ is not the constructor, merely an initializing routine).
The import is wrong.
Instead of
import repository
you want to write for your case:
from repository.repository import Repository
As for PyDev giving the error, it's correct at this point and when you fix your code it should stop complaining.

Categories

Resources