Using Hydra Configuration inside Classes - python

I am trying to use the hydra tool in my project and would like to use the decorator for class functions
import hydra
from hydra.core.config_store import ConfigStore
from src.config import RecordingConfig
cs = ConfigStore.instance()
cs.store(name="recording_config", node=RecordingConfig)
class HydraClassTest:
#hydra.main(config_path="../src/conf/", config_name="conf")
def __init__(self, conf: RecordingConfig):
print(conf)
def main():
HydraClassTest()
if __name__ == "__main__":
main()
But I get the error
TypeError: __init__() missing 1 required positional argument: 'conf'
Is this intended and should I pass the configuration from the outside to the class? (For example by using the decorator on the main function and passing the configuration as a parameter to the initializer, this works)
Or am using the decorator in a wrong way?
If it is intended, is there some design reason why one would not want to do it that way?
I have checked whether I used the decorator correctly by passing the configuration through the main function, that worked.
import hydra
from hydra.core.config_store import ConfigStore
from src.config import RecordingConfig
cs = ConfigStore.instance()
cs.store(name="recording_config", node=RecordingConfig)
class HydraClassTest:
def __init__(self, conf: RecordingConfig):
print(conf)
#hydra.main(config_path="../src/conf/", config_name="conf")
def main(conf: RecordingConfig):
HydraClassTest(conf)
if __name__ == "__main__":
main()
This gives me the expected result.

#hydra.main() is not appropriate for this use case. It's designed to be used once in an application and it has many side effects (changing working directory, configuring logging etc).
Use the Compose API instead.

Related

Using Abseil vs. Directly calling main()?

I've been using the vanilla
def main():
# Do stuff
if __name__ == '__main__':
main()
but recently saw people doing
from absl import app
def main(_):
# Do things
if __name__ == '__main__':
app.run(main)
Abseil provides flags.FLAGS, but I've been using ArgumentParser, which works perfectly fine, so there is no win for Abseil in this aspect.
Then, why bother go the Abseil route?
PS: Related discussion on Reddit (which doesn't really answer this question): https://www.reddit.com/r/Python/comments/euhl81/is_using_googles_abseil_library_worth_the/
Consider a design pattern, where you are passing a json file (that contains say site-specific constants) at the cmd line as input to your Python script. Say,the json file contains immutable constants and you want to maintain it that way.
You want the constants from json file contents to be made available to all the modules within your project.
One way to do this is by implementing a central module that deserializes the json into a Python object. ABSL helps you to solve this by accessing (via the FLAGS) the input file in the central module and then storing it into a class variable so all modules across your project can use this.
Without ABSL, you would need to first argparse the input file in main module, then send it to the central module.
A code example of this can be something like:
main.py:
from centralmod import DeserializeClass
import centralmod
from absl import flags
from absl import app
_JSON_FILE = flags.DEFINE_string("json_file", None, "Constants", short_name='j', required=True)
def scenario():
import someothermodule
someothermodule.do_something()
def populate_globalvar():
centralmod.populate_somevar()
deserialized_data = DeserializeClass.somevar
def main(argv):
populate_globalvar()
scenario()
if __name__ == '__main__':
app.run(main)
centralmod.py:
from absl import flags
import json
FLAGS = flags.FLAGS
class DeserializeClass:
#classmethod
def get_value(cls, key):
return DeserializeClass.somevar[key]
def populate_somevar():
with open(FLAGS.json_file) as json_constants_fh:
deserialized_data = json.load(json_constants_fh)
setattr(DeserializeClass, 'somevar', deserialized_data)
and someothermod.py:
from centralmod import DeserializeClass
site_specific_consts = DeserializeClass.somevar
def do_something():
print(f"\nScenario: Testing. The site-specific constants are:\n{site_specific_consts}")
print(f"the value of key ssh_key_file is {DeserializeClass.get_value('ssh_key_file')}")
print(f"the value of key nodes is {DeserializeClass.get_value('nodes')}")

What is the best way to pass arguments from a locust user to taskset parameters, where the tasksets have been separated to different files?

entry_point.py
from other_file import UserBehaviour
class ApiUser(HttpUser):
tasks = [UserBehaviour]
def on_start(self):
# log in and return session id and cookie
# example: self.foo = "foo"
other_file.py
from entry_point import ApiUser
class UserBehaviour(TaskSet):
#task
def do_something(self, session_id, session_cookie)
# use session id and session cookie from user instance running the taskset
# example: print(self.ApiUser.foo)
NOTE: Going through the documentation, I did find that "the User instance can be accessed from within a TaskSet instance through the TaskSet.user", however all my attempts to import the user into the taskset file led to a "cannot import name 'ApiUser' from 'entry_point'" error. If instead of from entry_point import ApiUser I do from entry_point import *, then I get a name 'ApiUser' is not defined error.
Thank you very much #Cyberwiz for putting me on the right track. I've finally managed to figure out what I was doing wrong... which, as it turns out, was a couple of things.
Firstly, importing ApiUser in other_file.py was incorrect for two reasons: 1) it creates a cyclical dependency, and 2) even if it would eventually work it would import the ApiUser class, not the instance of the ApiUser class.
Secondly, I was previously getting a module locust.user has no attribute {name} error, and that was because my code looked like this:
class UserBehaviour(TaskSet):
# do something with user.foo
Having figured this out, I honestly have no idea why I thought the above would work. I've changed my code to reflect the example below and everything now works like a charm:
class UserBehaviour(TaskSet):
#task
def do_something(self):
# do something with self.user.foo

Debug method of logging package isn't working

I have taken input from a form and passed them to this function from the kivy file (on_press property). The form data is fetched properly in the execute function but it won't get logged in myapp.log
Here's the code:
import logging
import selenium
class UIf(GridLayout):
def execute(self, *args):
print("First probe")
logging.basicConfig(filename="myapp.log", level = logging.DEBUG, format='%(asctime)s:%(message)s')
print("Second probe")
for name in args:
print("Third probe")
logging.debug(name)
class MyApp(App):
def build(self):
return UIf()
if __name__ == '__main__':
runapp = MyApp()
runapp.run()
Be sure to make your basicConfig call before importing any of kivy code, because it does its own, that could conflict with your parameters (especially output file).
Also, you might need to the debug level to DEBUG in kivy config, or to reset yourself the log level after the kivy import, because it reset it to its value.
I agree it's a bit intrusive and we should probably consider this a bug, though i don't know what the best way to both have good defaults and stay out of the way of people with opinions would be.

passing class methods in rpyc python

I have seen passing a functions using teleport_function, is there any way to pass class methods ?? or can I execute my class object remotely in any other way
I can alternative work around by making class a service . But that does not serve completely my requirement in my project.
import rpyc
from rpyc.utils.classic import teleport_function
def a(test):
print test
if __name__ = '__main__':
proxy = rpyc.classic.connect('remte.com')
launch_command_remote = teleport_function(proxy, a)
launch_command_remote("Voila") # Executed remotly

Problem with import in Python

[Closing NOTE]
Thank you everyone that trying to help me.
I've found the problem and it have nothing to do with python understanding of mine (which is little). :p
The problem is that I edit the wrong branch of the same project, Main.py in one branch and XWinInfos.py in another branch.
Thanks anyway.
[Original Question]
I am a Java/PHP/Delphi programmer and only use Python when hack someone else program -- never to write a complex Python myself. Since I have a short free time this week, I determine to write something non-trivia with Python and here is my problem
First I have python files like this:
src/
main.py
SomeUtils.py
In "SomeUtils.py, I have a few functions and one class:
...
def funct1 ...
def funct2 ...
class MyClass1:
__init__(self):
self. ....
...
Then in "main.py", I use the function and class:
from SomeUtils import *;
def main():
funct1(); # Use funct1 without problem;
aMyObj1 = MyClass1(); # Use MyClass1 with error
if (__name__ == "__main__"):
main();
The problem is that the functions are used without any problem what so ever but I cannot use the class.
The error is:
NameError: global name 'MyClass1' is not defined
What is the problem here? and What can I do?
EDIT: Thanks for answers for I still have problem. :(
When I change the import statements to:
from SomeUtils import funct1
from SomeUtils import MyClass1
I have this error
ImportError: cannot import name MyClass1
EDIT 2:----------------------------------------------------------
Thanks you guys.
I think, it may be better to post the actual code, so here it is:
NOTE: I am aware about ";" and "(...)" but I like it this way.
Here is the dir structure.
DIRS http://dl.getdropbox.com/u/1961549/images/Python_import_prolem_dir_.png
as you see, I just add an empty init.py but it seems to make no different.
Here is main.py:
from XWinInfos import GetCurrentWindowTitle;
from XWinInfos import XWinInfo;
def main():
print GetCurrentWindowTitle();
aXWinInfo = XWinInfo();
if (__name__ == "__main__"):
main();
Here is XWinInfos.py:
from subprocess import Popen;
from subprocess import PIPE;
from RegExUtils import GetTail_ofLine_withPrefix;
def GetCurrentWindowID():
aXProp = Popen(["xprop", "-root"], stdout=PIPE).communicate()[0];
aLine = GetTail_ofLine_withPrefix("_NET_ACTIVE_WINDOW\(WINDOW\): window id # 0x", aXProp);
return aLine;
def GetCurrentWindowTitle():
aWinID = GetCurrentWindowID();
aWinTitle = GetWindowTitle(aWinID);
return aWinTitle;
def GetWindowTitle(pWinID):
if (aWinID == None): return None
aWMCtrlList = Popen(["wmctrl", "-l"], stdout=PIPE).communicate()[0];
aWinTitle = GetTail_ofLine_withPrefix("0x[0-9a-fA-F]*" + aWinID + "[ ]+[\-]?[0-9]+[ ]+[^\ ]+[ ]+", aWMCtrlList);
return aWinTitle;
class XWinInfo:
def __init__(self):
aWinID = GetCurrentWindowID();
self.WinID = pWinID;
self.Title = GetWindowTitle(pWinID);
The file RegExUtils.py holds a function "GetTail_ofLine_withPrefix" which work fine so.
If I use "from XWinInfos import *;", the error goes "NameError: global name 'XWinInfo' is not defined".
If I use "from XWinInfos import XWinInfo;", the error goes "ImportError: cannot import name XWinInfo".
Please helps.
Thanks in advance.
Hmm... there's several typos in your example, so I wonder if your actual code has some typos as well. Here's the complete source from a quick test that does work fine without import errors.
SomeUtils.py:
def funct1():
print('Function 1')
def funct2():
print('Function 2')
class MyClass1(object):
def __init__(self):
print('MyClass')
main.py:
from SomeUtils import *
def main():
funct1()
aObj = MyClass1()
if (__name__ == "__main__"):
main()
[EDIT Based on OP additional info]
I still can't recreate the same error, but the code you posted won't initially work for at least a couple of errors in the XWinInfox.py init method:
self.WinID = pWinID #change to 'aWinID' since pWinID is not defined
self.Title = GetWindowTitle(pWinID) #change to 'aWinID'since pWinID is not defined
so a corrected version would read:
self.WinID = aWinID
self.Title = GetWindowTitle(aWinID)
Also, you have a typo in your init file name, there should be two underscores before AND after the 'init' word. Right now you have '__init_.py' and it should be '__init__.py', however this shouldn't keep your code from working.
Because I don't have the RegExUtils.py code, I just stubbed out the methods that rely on that file. With the stubbed methods and correcting the aforementioned typos, the code you post now works.
why are you importing from XWinInfos? you should be importing from SomeUtils. Not to mention that *-style imports are discouraged.
Edit: your error
ImportError: cannot import name MyClass1
basically tells you that there is no MyClass1 defined in the SomeUtils. It could be because you have another SomeUtils.py file somewhere on the system path and it being imported instead. If that file doesn't have MyClass1, you'd get this error.
Again: it's irrelevant whether you class MyClass1 exist. What might be the case is that you have another XWinInfos.p(y|o|w) somewhere on your system and it's being imported. Otherwise: norepro.
You may want to rewrite main.py as follows:
import SomeUtils as util
def main():
util.funct1() # Use funct1 without problem;
aMyObj1 = util.MyClass1() # Use MyClass1 with error
if __name__ == "__main__":
main()
A few quick notes:
There is no need for semicolons in
Python unless you have more than one
statement on a line
There is no need
to wrap conditional tests in
parentheses except for grouping
from
module import * is discouraged as it
pollutes the global namespace
I suppose you mean
from SomeUtils import *
however, that does not trigger the error for me. This works fine for me:
SomeUtils.py
def funct1():
print 4
class MyClass1:
def __init__(self):
print 8
main.py
from SomeUtils import *
def main():
funct1() # Use funct1 without problem;
aMyObj1 = MyClass1() # Use MyClass1 without error
if (__name__ == "__main__"):
main()
Your question is naturally linked to a lot of SO older one.
See, just for reference, SO1342128 and SO1057843

Categories

Resources