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)
Related
I am creating a commands system in Python. I have module vkcommands that has a class that processes commands from chat (this is a chat-bot), and inside it, I also have class VKCommand with attributes like name, usage, min_rank, etc. Then I have module vkcmds with submodules that implement these commands:
...
vkcommands.py
vkcmds
|- __init__.py # empty
|- add_group.py
|- another_cmd.py
|- ...
Implementations of commands (e.g. add_group) look like this:
import ranks
import vkcommands
from vkcommands import VKCommand
class AddGroup(VKCommand):
def __init__(self, kristy):
VKCommand.__init__(self, kristy,
label='create',
# ... (other attributes)
min_rank=ranks.Rank.USER)
def execute(self, chat, peer, sender, args=None, attachments=None):
# implementation (called from vkcommands.py)
When a user sends a message in the chat, the command manager analyzes it and looks through the registered commands list to see if this is an ordinary message or a bot command. Currently I register all commands in the commands list manually like this:
class VKCommandsManager:
def __init__(self, kristy):
from vkcmds import (
add_group,
next_class
)
self.kristy = kristy
self.commands = (
add_group.AddGroup(kristy),
next_class.NextClass(kristy)
)
Now I would like all commands to be registered automatically using reflections instead. In Java, I'd iterate over all classes in my commands package, reflectively getConstructor of each, call it to retrieve the VKCommand object, and add it to the commands list.
How can I do so in Python? Again, what I need is to:
iterate over all submodules in module (folder) vkcmds/;
for each submodule, check if there is some class X that extends VKCommand inside;
if (2) is true, then call the constructor of that class with one argument (it is guaranteed that the constructor for all commands only has one argument of a known type (my bot's main class));
add the object (? extends VKCommand) constructed in (3) to the commands list that I can iterate over later.
With this file structure:
- Project
├─ commands
| ├─ base.py
| ├─ baz.py
| └─ foo_bar.py
|
└─ main.py
And the following inside the commands directory files:
base.py
class VKCommand:
""" We will inherit from this class if we want to include the class in commands. """
baz.py
from commands.base import VKCommand
class Baz(VKCommand):
pass
def baz():
""" Random function we do not want to retrieve.
foo_bar.py
from .base import VKCommand
class Foo(VKCommand):
""" We only want to retrieve this command. """
pass
class Bar:
""" We want to ignore this class. """
pass
def fizz():
""" Random function we do not want to retrieve. """
We can retrieve the class instances and names directly using the following code:
main.py
"""
Dynamically load all commands located in submodules.
This file is assumed to be at most 1 level higher than the
specified folder.
"""
import pyclbr
import glob
import os
def filter_class(classes):
inherit_from = 'VKCommand'
classes = {name: info for name, info in classes.items() if inherit_from in info.super}
return classes
# Locate all submodules and classes that it contains without importing it.
folder = 'commands' # `vkcmds`.
submodules = dict()
absolute_search_path = os.path.join(os.path.dirname(__file__), folder, '*.py')
for path in glob.glob(absolute_search_path):
submodule_name = os.path.basename(path)[:-3]
all_classes = pyclbr.readmodule(f"commands.{submodule_name}")
command_classes = filter_class(all_classes)
if command_classes:
submodules[submodule_name] = command_classes
# import the class and store an instance of the class into the command list
class_instances = dict()
for submodule_name, class_names in submodules.items():
module = __import__(f"{folder}.{submodule_name}")
submodule = getattr(module, submodule_name)
for class_name in class_names:
class_instance = getattr(submodule, class_name)
class_instances[class_name] = class_instance
print(class_instances)
Explanation
The solution is twofold. It first locates all submodules that have a class which inherit from VKCommand and are located in the folder 'commands`. This leads to the following output containing the module and the class that have to be imported and instantiated respectively:
{'baz': {'Baz': <pyclbr.Class object at 0x000002BF886357F0>}, 'foo_bar': {'Foo': <pyclbr.Class object at 0x000002BF88660668>}}
The second part of the code imports the correct module and class name at run time. The variable class_instance contains the class name and a reference to the class which can be used to instantiate it. The final output will be:
{'Baz': <class 'commands.baz.Baz'>, 'Foo': <class 'commands.foo_bar.Foo'>}
Important notes:
The code only works when importing modules that are 1 dictionary deeper. If you want to use it recursively, you will have to locate the relative path difference and update the pyclbr.readmodule and __import__ with the correct (full) relative import path.
Only the modules that contain a class which inherit from VKCommand get loaded. All other modules are not imported, and have to be imported manually.
I believe that you can make an array of all the commands you have in your folder and then go over them and instantiate the objects.
in __init__.py
all_commands = [AddGroup, AnotherCmd, ...]
instantiate them like this:
objects = [Cmd(arg1, arg2, ...) for Cmd in all_commands]
Edit:
you could also retrieve the class names with the method that you said you had of getting all class names in the folder.
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?
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.
i want to make a sample package in python 2.7 just to clear my concepts whose structure looks like this:
calculator/
main.py
operations/
file1.py
file2.py
__init__.py
new_operations/
__init__.py
file3.py
main.py content: (this file is present inside calculator folder)
from operations import power
print power(2,2)
__init__.py content: (this file is present inside operations folder)
from .file1 import add
from .file1 import sub
from .file2 import mul
from .file2 import div
file1.py content: (this file is present inside operations folder)
def add(a,b):
return(a+b)
def sub(a,b):
return(a-b)
file2.py content: (this file is present inside operations folder)
def mul(a,b):
return(a*b)
def div(a,b):
return(a/b)
__init__.py content: (this file is present inside new_operations folder)
from .file3 import power
file3.py content: (this file is present inside new_operations folder)
def power(a,b):
return(a**b)
Now, when i run main.py, i got following error:
Traceback (most recent call last):
File "C:\Python27\mycodes\calculator\main.py", line 3, in <module>
from operations import power
ImportError: cannot import name power
Can anyone tell me, what mistake i am doing ? Help me.
Use the following line in your "main.py" file:
from operations.new_operations import power
You are missing an 'add' function in your calculator module. If you create an 'add' function, I would assume that the code would work.
maybe try doing this in the module calculator:
def add(num1,num2):
print(num1+num2)
return num1+num2;
If you don't want it to print while calculating, remove the print statement.
Hope this helps!
I've been trying to import some python classes which are defined in a child directory. The directory structure is as follows:
workspace/
__init__.py
main.py
checker/
__init__.py
baseChecker.py
gChecker.py
The baseChecker.py looks similar to:
import urllib
class BaseChecker(object):
# SOME METHODS HERE
The gChecker.py file:
import baseChecker # should import baseChecker.py
class GChecker(BaseChecker): # gives a TypeError: Error when calling the metaclass bases
# SOME METHODS WHICH USE URLLIB
And finally the main.py file:
import ?????
gChecker = GChecker()
gChecker.someStuff() # which uses urllib
My intention is to be able to run main.py file and call instantiate the classes under the checker/ directory. But I would like to avoid importing urllib from each file (if it is possible).
Note that both the __init__.py are empty files.
I have already tried calling from checker.gChecker import GChecker in main.py but a ImportError: No module named checker.gChecker shows.
In the posted code, in gChecker.py, you need to do
from baseChecker import BaseChecker
instead of import baseChecker
Otherwise you get
NameError: name 'BaseChecker' is not defined
Also with the mentioned folders structure you don't need checker module to be in the PYTHONPATH in order to be visible by main.py
Then in main.y you can do:
from checker import gChecker.GChecker