Python 'static core class' - python

Currently I'm making a game server, I actually want to make a base project for all my server products in Python. I used to use C# but I wanted to do something different so I started on Python. Although I don't know how to do something.
In C# I used to make one static 'core' class holding all data, containing the entry point and there I boot the server. Here's a small example:
using System;
namespace SERVER
{
public static class Engine
{
public static DatabaseHelper DatabaseHelper { get; private set; }
static void Main(string[] args)
{
DatabaseHelper = new DatabaseHelper();
}
}
}
Then I just could use in every class:
Engine.DatabaseHelper.SomeMethod();
Now, I want the same concept in my Python project, but I don't know how to do it.
I got this first:
DynamicEmu.py
import Engine
engine = Engine.Engine()
Engine.py
from Network.Game.GameConnectionListener import GameConnectionListener
class Engine:
gameConnection = None
def __init__(self):
gameConnection = GameConnectionListener()
def tuple_to_addr(self, tpl):
return '{0}:{1}'.format(tpl[0], str(tpl[1]))
And then in my GameConnectionListener.py I would use:
import DynamicEmu
In order to do
DynamicEmu.engine.tuple_to_addr(TUPLE HERE)
But I get this error
Traceback (most recent call last):
File "C:/Users/Josh/PycharmProjects/DynamicEmu/DynamicEmu.py", line 1, in <module>
import Engine
File "C:\Users\Josh\PycharmProjects\DynamicEmu\Engine.py", line 3, in <module>
from Network.Game.GameConnectionListener import GameConnectionListener
File "C:\Users\Josh\PycharmProjects\DynamicEmu\Network\Game\GameConnectionListener.py", line 4, in <module>
import DynamicEmu
File "C:\Users\Josh\PycharmProjects\DynamicEmu\DynamicEmu.py", line 3, in <module>
engine = Engine.Engine()
AttributeError: module 'Engine' has no attribute 'Engine'
I suck in Python so if I'm doing something REALLY wrong I understand, I want to learn so I'd appreciate every piece of help I can get :)

Typical Python code doesn't use static members very much.1 So I would advise making most of your variables instance variables. For instance, in DynamicEmu.py, don't have a module-level Engine instance. Instead, have a class which is initialized with an Engine instance
class DynamicEmu:
def __init__(self, engine):
self.engine = engine
...
or a function that accepts an Engine instance as an argument
def dynamic_emu(engine):
...
It's hard to be more specific without knowing what the code in DynamicEmu.py is supposed to do.
Similarly, in GameConnectionListener.py you would define your listener like
class GameConnectionListener:
def __init__(self, engine):
self.engine = engine
...
and so on with other code. (Bear in mind that Python functions are objects, and can be passed as arguments and used as callbacks. Consider whether you could get away with a function, not a class.)
Obviously, that Engine instance has to be created somewhere. A logical place might be in your main() function, or in some setup function that gets called early in the program. You can then pass it around to other functions and methods as needed.
In my experience, writing a large project tends to work out best when you are clear about the dependencies between different parts of the code. For example, be clear about whether the game engine uses the listener or the listener uses the game engine. If the engine uses the listener, then you should be using GameConnectionListener in Engine, but not vice-versa. The GameConnectionListener should be designed in a way that it doesn't know about the Engine. This isn't always possible, of course, but to whatever extent you can do it, I think it helps. It reduces or eliminates circular dependencies as you have in your example code, and it also helps you write each component of the program separately without having to worry about others at the same time.
1Or, what C# calls static members; in Python they're called class members, but nearly the same functionality is often provided by module-level variables, which are simpler.

Related

Pythonnet TypeError when initializing class

I'm trying to access a class inside a .dll file using pythonnet and I am unable to create and instance of a class without the following error. I'm using the latest version of pythonnet (2.5.2) and Python 3.10.5.
Error
Traceback (most recent call last):
x = IDispenser()
TypeError: interface takes exactly one argument
Python Code
import clr
import sys
dll_path = "C:\\Program Files\\Seyonic\\Dispenser Control Monitor 3.8"
if dll_path not in sys.path:
sys.path.append("C:\\Program Files\\Seyonic\\Dispenser Control Monitor 3.8")
assert dll_path in sys.path
clr.AddReference("Seyonic.Dispenser")
from Seyonic.Dispenser import IDispenser
x = IDispenser()
DLL
namespace Seyonic.Dispenser
{
public interface IDispenser
{
// ----------------------------------------------------------------------------
// Properties
// ----------------------------------------------------------------------------
int Data { get;}
...etc
}
}
After digging through the dll file (doesn't seem to take any arguments for using these classes) I think this is a pythonnet / python3 problem. Here is an excerpt from https://github.com/DynamoDS/Dynamo/wiki/Work-in-progress-to-improve-Python-3-support:
Python classes cannot implement .NET interfaces (Not planned)
This is probably an advanced usage scenario of Python and interoperability with .NET. Here a Python class is defined in such a way that it implements a .NET interface. The idea behind this is that instances of the class can be created and passed as arguments to methods accepting them. Here is an example of how this could look like:
import clr
clr.AddReference('SomeLibrary')
from SomeLibrary import SomeInterface, SomeClass
class MyClass(SomeInterface):
def __init__(self):
pass
inst = MyClass()
result = SomeClass.SomeMethodTakingSomeInterface(inst)
OUT = result
Given a valid library was provided, the previous code sample would work without issues in the IronPython2 engine. When using CPython3, however, you can get TypeError : interface takes exactly one argument or TypeError : object does not implement SomeInterface, depending on the interface and method definitions. The required changes in Python .NET to make this work seem big when compared to the relevance we have detected for this use case, so we have decided to not plan this work yet.

Should I always use the most pythonic way to import modules?

I am making a tiny framework for games with pygame, on which I wish to implement basic code to quickly start new projects. This will be a module that whoever uses should just create a folder with subfolders for sprite classes, maps, levels, etc.
My question is, how should my framework module load these client modules? I was considering to design it so the developer could just pass to the main object the names of the directories, like:
game = Game()
game.scenarios = 'scenarios'
Then game will append 'scenarios' to sys.path and use __import__(). I've tested and it works.
But then I researched a little more to see if there were already some autoloader in python, so I could avoid to rewrite it, and I found this question Python modules autoloader?
Basically, it is not recommended to use a autoloader in python, since "explicit is better than implicit" and "Readability counts".
That way, I think, I should compel the user of my module to manually import each of his/her modules, and pass these to the game instance, like:
import framework.Game
import scenarios
#many other imports
game = Game()
game.scenarios = scenarios
#so many other game.whatever = whatever
But this doesn't looks good to me, not so confortable. See, I am used to work with php, and I love the way it works with it's autoloader.
So, the first exemple has some problability to crash or be some trouble, or is it just not 'pythonic'?
note: this is NOT an web application
I wouldn't consider letting a library import things from my current path or module good style. Instead I would only expect a library to import from two places:
Absolute imports from the global modules space, like things you have installed using pip. If a library does this, this library must also be found in its install_requires=[] list
Relative imports from inside itself. Nowadays these are explicitly imported from .:
from . import bla
from .bla import blubb
This means that passing an object or module local to my current scope must always happen explicitly:
from . import scenarios
import framework
scenarios.sprites # attribute exists
game = framework.Game(scenarios=scenarios)
This allows you to do things like mock the scenarios module:
import types
import framework
# a SimpleNamespace looks like a module, as they both have attributes
scenarios = types.SimpleNamespace(sprites='a', textures='b')
scenarios.sprites # attribute exists
game = framework.Game(scenarios=scenarios)
Also you can implement a framework.utils.Scenario() class that implements a certain interface to provide sprites, maps etc. The reason being: Sprites and Maps are usually saved in separate files: What you absolutely do not want to do is look at the scenarios's __file__ attribute and start guessing around in its files. Instead implement a method that provides a unified interface to that.
class Scenario():
def __init__(self):
...
def sprites(self):
# optionally load files from some default location
# If no such things as a default location exists, throw a NotImplemented error
...
And your user-specific scenarios will derive from it and optionally overload the loading methods
import framework.utils
class Scenario(framework.utils.Scenario):
def __init__(self):
...
def sprites(self):
# this method *must* load files from location
# accessing __file__ is OK here
...
What you can also do is have framework ship its own framework.contrib.scenarios module that is used in case no scenarios= keyword arg was used (i.e. for a square default map and some colorful default textures)
from . import contrib
class Game()
def __init__(self, ..., scenarios=None, ...):
if scenarios is None:
scenarios = contrib.scenarios
self.scenarios = scenarios

Is it better to call functions in middle of script or at end of script? Python 2.7

I have a few python scripts, and each one of them consist of multiple functions. I was wondering if it is better (meaning faster, and cleaner) to run the function right after the function is created, or to create all of the functions, and then run them in order at the end of the script. when I say "run them" I mean calling myfunction() after the function is over, or waiting for the end of the script and calling something like:
myFunction()
myFunction2()
myFunction3()
I'll add a little more detail. I have 4 scripts, each of them consist of functions that must be used from other scripts. for example I have one script that, grabs a users login information and logs them into a website, cancels their account, and then returns their data from said site. then I have a scrip that will resume their account, but in order to do so I need to use the login function from the previous script. So I was wondering if, since I am using each function in multiple scripts if it was more efficient to call them all at the end using a "name==main" or to just call them as I create them.
It actually depends on your need and programming practices, so none of them is better over other
If you want to keep your code clean, I would suggest that keep all the similar functions in a class then import that class in another class where you can call the function on the object/ class
Example
File : user.py
class Essential(object):
def init(self, name):
self.name = name
def getName(self):
return self.name
File : main.py (here we will actually run the app/ entry-point for the app)
from user import Essential
if __name__=='__main__':
obj = Essential('John')
name = obj.getName()
print(name)
This will keep everything bit modular and easy to manage both physically and logically

Global variable is undefined at the module level

(There are many similar and more generic questions, been trying the solutions from them after reading through them, can't get them working so asking here as a more situation-specific version of what I'm seeing)
I think I am really miss-understanding how Python does OOP due to my more C#/C++ background. So here's what I'm trying to do right this moment.
I'm starting with two modules to set up the rest of my project, partially as a sanity-check and proof-of-concept. One module logs things to a file as I go while also storing data from multiple modules (to eventually package them all and dump them on request) Doing all this in PyCharm and mentioning the error warnings it suggests by the way, and using Python 2.7
Module 1:
src\helpers\logHelpers.py
class LogHelpers:
class log:
def classEnter():
#doing stuff
def __init__(self):
self.myLog = LogHelpers.log() #forgot to mention this was here initially
[..] various logging functions and variables to summarize what's happening
__builtin__.mylogger = LogHelpers
Module 2:
src\ULTs\myULTs.py
mylogger.myLog.classEnter()
(both the modules and the root src\ have an empty init.py file in them)
So according to the totally awesome response here ( Python - Visibility of global variables in imported modules ) at this stage this should be working, but 'mylogger' becomes an 'unresolved reference'
So that was one approach. I also tried the more straight forward global one ( Python: How to make a cross-module variable? )
Module 1:
src\helpers\logHelpers.py
class LogHelpers:
class log:
def classEnter(self):
#doing stuff
def __init__(self):
self.myLog = LogHelpers.log() #forgot to mention this was here initially
[..] various logging functions and variables to summarize what's happening
mylogger = LogHelpers
__init__.py
__all__ = ['LogHelpers', hexlogger]
from .logHelpers import *
Module 2:
src\ULTs\myULTs.py
from helpers import mylogger
mylogger.myLog.classEnter()
This version gets a "parameter 'self' unfilled" error on the classEnter, which various reports seem to indicate means that mylogger is un-initialized (misleading error code but that's what it seems to mean)
And then I tried this..
Module 1:
src\helpers\logHelpers.py
class LogHelpers:
class log:
def classEnter(self):
#doing stuff
def __init__(self):
self.myLog = LogHelpers.log() #forgot to mention this was here initially
[..] various logging functions and variables to summarize what's happening
__mylogger = LogHelpers
__init__.py
__all__ = ['LogHelpers', hexlogger]
from .logHelpers import *
Module 2:
src\ULTs\myULTs.py
from helpers import mylogger
def someFunction(self):
global mylogger
mylogger.myLog.classEnter()
And this version gets the 'Global variable is undefined at the module level' error when I hover of global mylogger.
Then there is the idea of each other module tracking its own instance of a class apparently, if I end up having to I can go with that method and coordinate them.. but that's kind of a hack considering what I'm trying to do.
That's kind of where I'm at, that's the gist of what I'm trying to do... I'm reading through as many similar questions as I can but all of them seem to come back to these kinda of solutions (which don't seem to be working) or saying 'don't do that' (which is generally good advice but I'm not really grocking the preferred Pythony way of keeping multiple ongoing non-static classes organized for a large project - other than shoving them all in one directory)
Thoughts? (How badly am I mangling Python here?)
[EDIT] Based on feedback tried a mini version that eliminated the inner classes completely:
Ok, so did a local mini-class based on what you said:
class testClass:
def __init__(self):
self.testVar = 2
def incrementVar(self):
self.testVar += 1
myClass = testClass()
Set it up via init.py
__all__ = [myClass]
from .logHelpers import myClass
Went to other module and
from helpers import myClass
class Test_LogHelpers(unittest.TestCase):
def test_mini(self):
myClass.incrementVar()
Ran it directly instead of looking at PyCharm, no Global anything.. NameError: name 'myClass is not defined
So still at square one :( (and still need to store state)
[EDIT] Adding Traceback:
Traceback (most recent call last):
File "C:\Program Files (x86)\JetBrains\PyCharm Community Edition 3.4.1\helpers\pycharm\utrunner.py", line 124, in <module> module = loadSource(a[0])
File "C:\Program Files (x86)\JetBrains\PyCharm Community Edition 3.4.1\helpers\pycharm\utrunner.py", line 40, in loadSource module = imp.load_source(moduleName, fileName)
File "C:\[...mylocation...]\py\src\ULTs\LogHelpers_ULT.py", line 3, in <module> from helpers import myClass
File "C:\[...mylocation...]\py\src\helpers\__init__.py", line 7, in <module>
__all__ = [myClass]
NameError: name 'myClass' is not defined
============================================================================
kk, I got it working with the miniclass. I don't know why the other approach / approaches was not working, but this seemed to fix things.
(Resources: http://docs.python-guide.org/en/latest/writing/structure/ , http://mikegrouchy.com/blog/2012/05/be-pythonic-__init__py.html )
**logHelpers.py**
[... some static logging functionality ...]
class testClass:
def __init__(self):
self.testVar = 2
def incrementVar(self, source):
self.testVar += 1
mylogger.myLog.info(source + " called, new val: " + str(self.testVar))
myClass = testClass()
**test_LogHelpers_ULT.py**
import unittest
from helpers.logHelpers import myClass
class Test_LogHelpers(unittest.TestCase):
def test_mini(self):
myClass.incrementVar("LogHelpers")
For some reason skipping the
init.py
(and leaving it blank) and going for the explicit importation worked. It also maintained state - I created a duplicate of the test file and my log output correctly had '3' for the first file to call the helper, and '4' for the second file to call the helper.
Thanks Daniel Roseman for the help and suggestions, they had me look a bit more in the right direction. If you can spot why the previous stuff wasn't working it would be much appreciate just to add to my understanding of this language, but I'm gonna go ahead and mark your answer as 'Answered' since it had some very useful feedback.
Before I start, note that the PyCharm warnings are not actual Python errors: if you ran your code, you would probably get more useful feedback (remember static analysis of a dynamic language like Python can only get you so far, many things can't be resolved until you actually run the code).
Firstly, it's really not clear why you have nested classes here. The outer class seems completely useless; you should remove it.
The reason for the error message about "self" is that you have defined an instance method, which can only be called on an instance of log. You could make mylogger (absolutely no need for the double-underscore prefix) an instance: mylogger = log() - and then import that, or import the class and instantiate it where it is used.
So in your first snippet, the error message is quite clear: you have not defined mylogger. Using my recommendation above, you can do from helpers import mylogger and then directly call mylogger.classEnter().
Finally, I can't see what that global statement is doing in someFunction. There's no need to declare a name as global unless you plan to reassign it within your scope and have that reassignment reflected in the global scope. You're not doing that here, so no need for global.
By the way, you should also question whether you even need the inner log class. Generally speaking, classes are only useful when you need to store some kind of state in the object. Here, as your docstring says, you have a collection of utility methods. So why put them in a class? Just make them top-level functions inside the logHelpers module (incidentally, Python style prefers lower_case_with_underscore for module names, so it should be "log_helpers.py").

Python/Plone - Is it possible to call a global utility at module level of a py file?

I have a product for a plone site with a module containing a utility class, and in the module that will/should use this utility, I am trying to have it setup at the module level.
In the module containing the utility (my.product.testutility), I have this:
from five import grok
from zope.interface import Interface
class ITestUtil(Interface):
"""Interface of utility
"""
def returnTest(self):
"""return a string for now
"""
class TestUtil(object):
"""Utility class test
"""
grok.implements(ITestUtil)
def returnTest(self):
return "testing"
grok.global_utility(TestUtil, name="TestUtility")
In the module that will use this utility (my.product.stringtesting):
from five import grok
from my.package.testutility import ITestUtil
from zope import component, schema
from Products.CMFCore.interfaces import ISiteRoot
utilForTesting = component.getUtility(ITestUtil, name="TestUtility")
class IStringTest(Interface):
......
class View(grok.View):
def returnStringForTest(self):
return utilForTesting.returnTest()
I also had the template file that would call the returnStringForTest to display the string on the rendered page.
I end up getting this error unfortunately:
ComponentLookupError: (< InterfaceClass my.product.testutility.ITestUtil >, "TestUtility")
I did try several different things like using grok.GlobalUtility as a base as opposed to making it an object registering it through grok.global_utility. I did remove the name parameter in the class using this while testing this.
The documentation I was trying to follow was the References on the grok site, looking at the directives page where it has the global utility information.
Also, I am using grok 0.9.
Edit:
The version of Plone I am using is Plone 4 and the version of python I am using is 2.7.
Is it possible to have the utility set up at the module level like I was trying?
You can do what you want without relying on Zope at all.
You can change the line in my.product.stringtesting:
from
utilForTesting = component.getUtility(ITestUtil, name="TestUtility")
to
utilForTesting = TestUtil()

Categories

Resources