blob: 5d372f163fc9362f9f8f911a906c729d20ab0dcc [file] [log] [blame]
import sys
import os
from multiprocessing import Pool, cpu_count, Process
import json
def _except_hook(cls, exception, traceback):
'''
Function used by :py:func:`pqt5_exception_workaround`. Don't call this directly.
'''
sys.__excepthook__(cls, exception, traceback)
def pqt5_exception_workaround():
'''
Workaround to prevent pyqt5 from silently eating exceptions.
Call this at the beginning of your progame and you will experience relieve.
'''
sys.excepthook = _except_hook
class Persival():
'''
Keeps values persistent between program runs.
'''
def __init__(self, persival_file='persival.json'):
'''
Will try to load parameters from the persival_file.
If the file does not exists this will be silently ignored and the file will be created when :py:meth:`save` will be called.
'''
self.persival_file=persival_file
if os.path.exists(persival_file):
with open(self.persival_file, 'r') as file:
self.data=json.load(file)
else:
self.data={}
def setDefault(self, name, value):
'''
Sets the given value only if no information was present in the persival file or if the persival file was not found.
'''
if not name in self.data.keys():
self.data[name]=value
def get(self, name):
'''
Returns the saved value for the given parameter.
'''
return self.data[name]
def set(self, name, value):
'''
Store the given value in memory. You have to call save to dump the value to the disk.
'''
self.data[name] = value
# print('Break')
def save(self):
'''
Saves the content to a file.
'''
with open(self.persival_file, 'w') as file:
json.dump(self.data, file)
class ProcessingHelper():
'''
Helper working around the limitations of Pool.
'''
def __init__(self, parallel=False, maxCpu=None):
self.funcs=[]
self.parallel=parallel
self.maxCpu=maxCpu
self.retval=[]
def add(self, function, args, kwargs={}):
'''
Add a function to the processing pool.
:param function: function to be executed
:param args: list. Provice the positional arguments
:param kwargs: dict. Optional, provide the kwargs
'''
if self.parallel:
self.funcs.append({'func': function, 'args': args, 'kwargs': kwargs})
else:
retval=function(*args, **kwargs)
self.retval.append(retval)
def run(self):
'''
Start processing.
:returns: list of results. The orgdering matches the sequence of add calls.
'''
processes=cpu_count()
if not self.maxCpu is None:
processes=min(self.maxCpu, processes)
# Windows does not handle full cpu loads well, so leave one CPU unutilized for Windows.
if os.name == 'nt':
processes -=1
if self.parallel:
with Pool(processes=processes) as pool:
result=pool.map(self._myrun, range(len(self.funcs)))
else:
result=self.retval
return result
def _myrun(self, paramNo):
'''
wrapper around the function for pool
:param paramNo:
'''
param=self.funcs[paramNo]
func=param['func']
args= param['args']
kwargs= param['kwargs']
retval=func(*args, **kwargs)
return retval