Can't instantiate Python class even though it's being imported - python

I'm writing a Python package that looks like this:
|- datum/
|- __init__.py
|- database.py
__init__.py
from .database import Database
def connect(url):
print(Database) # for debugging
return Database(url)
database.py
class Database(object):
def __init__(self, url):
self.url = url
...more methods
This is installed as a package called datum in development mode. If I call connect outside of this package like:
import datum
db = datum.connect('postgresql://xxx')
...this is the output:
<class 'datum.database.Database'>
Traceback (most recent call last):
File "Z:\AIS\Flask\ais\engine\scripts\load_pwd_parcels.py", line 30, in <module>
source_db = Database(source_db_url)
NameError: name 'Database' is not defined
I'm confused because the class is being imported fine -- I can print it and even run dir on it and see all my methods -- but when I try to instantiate something it's "not defined". Does anyone know what I'm doing wrong here?

A NameError means that a local or global name cannot be found. I would make sure that your "load_pwd_parcels.py" file includes:
from database import Database
Alternatively, you could do:
import database
source_db = database.Database(source_db_url)
The latter option is a great choice because it gives database its very own namespace. In the words of Tim Peters in PEP 20 -- The Zen of Python:
"Namespaces are one honking great idea - let's do more of those!"

Related

import on Python doesn't work as expected

Although the variable should be imported, I get "name X is not defined" exception.
main.py
from config import *
from utils import *
say_hello()
utils.py
from config import *
def say_hello():
print(config_var)
config.py
from utils import *
config_var = "Hello"
Trying to run "main.py":
Traceback (most recent call last):
File "main.py", line 3, in
say_hello()
File "C:\Users\utils.py", line 3, in say_hello
print(config_var)
NameError: name 'config_var' is not defined
What happened here? Why some_var is not accessible from utils.py?
You are importing config in util and util in config which will causing this error(create cross loop). remove from utils import * from config.py and then try this.
And in main.py you don't need to import the from config import * unless you are using variables from config directly in your main()
you should also import config.config_var, since this variable belongs to that specific module
You are creating to many import statements perhaps try the following below, but also you need to define a parameter in utils.py if you are passing a parameter through there.
In utils.py we require a parameter to be passed since you want to print out the appropriate value, In config.py you are defining a value. Then in main.py as discussed before using the wildcard operator "*" isn't entirely good in this situation then in order to call the respective functions you need to address them through their file name
In utils.py :
def say_hello(config_var):
print(config_var)
In config.py
config_var = "Hello"
Then in main.py
import config as cn
import utils as ut
ut.say_hello(cn.config_var)
Check out this thread for how to write python modules as well How to write a Python module/package?

Importing * in Python 3.7 Using __init__.py File

First of all here is my directory structure:
Root
- models
car.py
__init__.py
hello.py
Inside __init__.py I have the following:
__all__ = ["car"]
Inside hello.py I try to import everything from models folder:
from models import *
car = Car()
This gives me the error:
Traceback (most recent call last):
File "hello.py", line 4, in <module>
car = Car()
NameError: name 'Car' is not defined
What am I doing wrong?
You will have to specify what class you would like to import into the attribute __all__ of your __init__.py file. See below the example:
from car import *
__all__ = ["Car"]
If you want to have the class Car directly accessible in hello.py after you do from models import *, in the __init__.py file, put from models.car import Car.
__all__, on the other hand, typically lists names of modules, like what you have above. You could change hello.py to be as follows and your current __init__.py that consists of __all__ = ["car"] will work:
from models import *
car_obj = car.Car() # Reference module.class instead of just the class
From the python docs:
if a package’s __init__.py code defines a list named __all__, it is taken to be the list of module names that should be imported when from package import * is encountered.
This means that your hello.py has just imported the car module into it's namespace, not the Car class. Therefore this would work.
from models import *
auto = car.Car()
You missed one step there.
Try:
from models import *
car = car.Car()
Or try:
from models.car import *
car = Car()
__all__ just controls what will be exported by using * in current scope.
In your case, Car is not in your __init__.py's scope. So it is meaningless.
To solve this problem, you need to import Car into __init__.py's scope, that's all.
I understand that you think just by using __all__, you can directly access the class in car.py, but that's not true. __all__ does nothing else but control exports in current scope.

how to import a python class's moudle?

I have this main.py, in it:
import uuid
class tools(object):
def generate_uuid(self):
return self.uuid.uuid4()
in my calling program callmain.py, I have
import main
result = main.tool.generate_uuid()
print ("result")
if I run my callmain.py: I get
"TypeError: generate_uuid() missing 1 required positional argument:
'self'
if I add self to the line
result = main.tool.generate_uuid(self): I get
NameError: name 'self' is not defined
How to fix this? thank for help.
because you should make a object from your class first. then call your sub function like this:
import main
result = tools()
result.generate_uuid()
print(result) # "result" is a string! you should just call result without any "".
If you want to use the module of a class you have to create an instance of that class first and call if from that instance, that way the self argument is passed a valid reference to an instance of that class. For example:
import main
tools_instance = main.tools()
result = tools_instance.generate_uuid()
The style of importing shown in your question looks like a package. In packages a folder of python files __init__.py can be arranged in a particular way, documented here Python Packages. An example from the docs
parent/
__init__.py
one/
__init__.py
two/
__init__.py
three/
__init__.py
So an package of the format
main/
__init__.py
tools/
__init__.py # Add function 'generate_uuid' in this file
Could be utilized as follow:
import main
result = main.tools.generate_uuid()
print(result)

Multiple modules , single instance of a class - Python

I have two modules misc.py and main.py and would like to define all classes present in misc.py in main.py.
Below is the code
#misc.py
class dummy:
def __init__(self):
pass
def dummyPrint(self):
print "Welcome to python"
#main.py
import misc
dummyObj = dummy()
dummyObj.dummyPrint()
Is this the right way to go ? I do not see any output i.e., Welcome to python
$python misc_main.py misc.py
EDIT: I added the statement from misc import dummy and i am getting the following error
$python misc_main.py main.py
Traceback (most recent call last):
File "misc_main.py", line 5, in <module>
dummyObj = dummmy()
NameError: name 'dummmy' is not defined
When you do the following command, you are calling misc_main.py from the interpreter with misc.py as an argument.
python misc_main.py misc.py
Since misc_main is not reading command line arguments, this is equivalent to
python misc_main.py
I am surprised that you do not get errors, in either case. You need to import the actual class if you want to get output.
from misc import dummy
dummyObj = dummy()
dummyObj.dummyPrint()
Note, I am assuming your main file is actually in called misc_main.py rather than main.py as you have stated in your question. Otherwise you are not invoking the correct file.

Writing and importing custom modules/classes

I've got a class that I'm trying to write called dbObject and I'm trying to import it from a script in a different folder. My structure is as follows:
/var/www/html/py/testobj.py
/var/www/html/py/obj/dbObject.py
/var/www/html/py/obj/__init__.py
Now, __init__.py is an empty file. Here are the contents of dbObject.py:
class dbObject:
def __init__():
print "Constructor?"
def test():
print "Testing"
And here's the contents of testobj.py:
#!/usr/bin/python
import sys
sys.path.append("/var/www/html/py")
import obj.dbObject
db = dbObject()
When I run this, I get:
Traceback (most recent call last):
File "testobj.py", line 7, in <module>
db = dbObject()
NameError: name 'dbObject' is not defined
I'm new to Python, so I'm very confused as to what I'm doing wrong. Could someone please point me in the right direction?
EDIT: Thanks to Martijn Pieters' answer I modified my testobj.py as follows:
#!/usr/bin/python
import sys
sys.path.append("/var/www/html/py")
sys.path.append("/var/www/html/py/dev")
from obj.dbObject import dbObject
db = dbObject()
However, now when I run it I get this error:
Traceback (most recent call last):
File "testobj.py", line 7, in <module>
db = dbObject()
TypeError: __init__() takes no arguments (1 given)
Is this referring to my init.py or the constructor within dbObject?
EDIT(2): Solved that one myself, the constructor must be able to take at least one parameter - a reference to itself. Simple fix. Looks like this problem is solved!
EDIT (Final): This is nice - I can cut out the import sys and sys.path.append lines and it still works in this instance. Lovely.
You need to import the class from the module:
from obj.dbObject import dbObject
This adds the class dbObject directly to your local namespace.
Your statement import obj.dbObject adds the name obj to the local namespace, so you could also do this instead:
db = obj.dbObject.dbObject()
because obj.dbObject is the dbObject.py module in your obj package directory.

Categories

Resources