Package: sine.utils
sine.utilsthe set of common toolstoolsClass ConfigFileAloneSimplify read/write on a Json config file. Based on module config_file.
Main features:Most used in single program to create and read from a local config file.Specify your default config value in your code and then it will be add to the file.Don't worry about whether the file exists, and ONLY when config changed the file will be saved.try:config=ConfigFileAlone('json_file_path')save_path=config.getAlone('prop1','default')api_path=config.getAlone('prop2',2)# ... your workconfig.saveAlone()exceptException:print("can not load config file")Class PredictableProcessBarProcess bar just wrap module tqdm and provide new members to make the progress change more smoothly when the unit size is not equivalent and keep unknown in some time and need to predict. Using simple algorithm. For example, to download 100 picture from the website, you create 10 threads to do this, you set the origin total to 100 and never know the true size of the picture you have not read in.importrequestsfromsine.utilsimport*bar=PredictableProcessBar(total=100)defdownload_pic(url,path,bar):withclosing(requests.get(url,stream=True))asresp:size=int(resp.headers['Content-Length'])# you now know the true 'size' of one of origin total size in the bar, call this for adjust the true process and help to predictionbar.load_in(size,1)withopen(path,'wb')ascode:forchunkinresp.iter_content(chunk_size=1024*1024):# buffer size: 1MBcode.write(chunk)# send the true size just for log, and the origin size for update, and optional the core cost time for logbar.update_out(len(chunk),len(chunk)/size)bar.set_postfix_str(byte2readable(bar.loaded_avg*bar.n/(time.time()-bar.start_t))+'/s')Class EventManagerprovide event sending and listening.
use a hashable key to identify an event.deff(key,data):print(data)manager=EventManager()manager.start()# start listenmanager.addListener(key='evnet_key',listener=f)manager.sendEvent(key='evnet_key','print hello')# other methodsmanager.removeListener(key='evnet_key',f)manager.stop()# stop listenmanager.clear()# clear eventClass Pathconvenient to join file path in a chain manner:s=Path('.')s=s.join('a','b').join('..')# s == 'a'it usesos.path.joinand always normalizes the path withos.path.normpathbecauseos.path.joinjoin the'a', '..'to'a/..'Module propertiesread/write .properties file in line-oriented formatkey=valueper linethrough function.the code refers tojava.util.Propertiesin Java 1.6.Common Usagefile I/O:# inputproperties=load(file)# or update existing dictionaryload(file,properties)# outputstore(file,properties)custom input:class LineReaderread in one key-value data. It skips all comment lines,blank lines, leading whitespace, and processes multi-line data.loadSingle(string)read each piece of data given above to key-value.forlineinLineReader(file):# each key-value line has no line seperatorkey,value=loadSingle(line)# do somethingcustom output:storeComments(writable, comments, linesep=os.linesep))write comment (accept multi-line), can specify the line terminator.storeSingle(writable, key, value, sep='=', linesep=os.linesep)write one key-value, can specify the seperator and the line terminator.storeComments(file,'this is a comment')storeSingle(file,'key','value')File Formatnormally each line is comment line or a key-value pair.main features:seperate key and value by one of=,:,,\tignore whitespaces leading in a line or around=or:comment line begin with#or!escape unicode by\uxxxxescape special characters by adding\others:data line ends with\discard the line breakdifferences with Java:store method will not write datetime commentThread classesdeffunc(a,b,stop_event):while1:ifstop_event.is_set():break# do your workthread=StoppableThread(target=func,args=('a','b'))thread.start()# ...thread.stop(-1)# stop and join forever# thread.stopped() == Truethread=ReStartableThread(target=func,args=('a','b'),event_name='stop_event')# can specify the parameter's namethread.start()# ...thread.stop(1)# stop and join for 1 second# ...thread.start()# ...thread.stop()thread.join()# ...sine.storageBriefprovide simple reliable persistence for string data base on a string key.data changes will append to the file like logging while update.
data are store incsvformat.
you can compress the data anytime reliably.Examples# common usestorage=getStorage('./data.csv')author=storage.setdefault('author','sine')storage['author']='Sine'delstorage['author']forkinstorage.keys():print(k,storage[k])# compress datastorage.compress()Change Logv0.2.1, 2021-12-26[fix] using Thread.is_alive instead of Thread.isAlive (not found)[fix] bugs in PredictableProcessBarv0.2.0, 2021-12-26[new] class PredictableProcessBar[new] class ConfigFileAlone[new] functional: byte2readable, mkdir[fix] using collections.abc.Iterablev0.1.1, 2019-12-14EventManager's process thread defaults to be daemon, can be set.v0.1.0, 2019-7-21collect from exist package:sine.path-v0.1.3sine.threads-v0.1.7sine.event-v0.0.2sine.properties-v0.1.1and the new 'storage'.news:EventManager: change arguments passing, include the key (just like calling the sendEvent)threads: fix about args appending