{ "info": { "author": "Rouzbeh Afrasiabi", "author_email": "rouzbeh.afrasiabi@gmail.com", "bugtrack_url": null, "classifiers": [ "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python :: 3.6" ], "description": "# loopimer\n
\nPackage for time-controlled consecutive execution of a function using threading. Allows control over the time between each function execution and the introduction of time delays/pauses. Furthermore, the package utilizes Queues and slicing to provide the user with the ability to control the execution of the looping function using queued slices. The package was originally developed for working with rate limited APIs and only uses python standard libraries.\n
\n\n## Requirements\n### Python Standard Libraries\n - threading\n - time\n - datetime\n - queue\n - math\n - sys\n - os\n \n## Installation\n\n```\npip install loopimer\n```\n\n```\npip install git+https://github.com/rouzbeh-afrasiabi/loopimer.git\n```\n\n## Decorators:\n - loopimer\n \n## Examples\n\n### Importing \n```python\nfrom loopimer import *\n```\n### Usage: \n\n\nIn the simplest usage case, you pass a value in seconds to the decorator through the 'every' variable. This will modify the\nfunction that is declared after the decorator to execute every x seconds as an indefinite loop when called.\n
\n\n```python\n#cauion: infinite loop\n@loopimer(every=5)\ndef test(loop,): \n print('loopimer')\ntest() \n```\n\n\nSetting 'every' to zero will remove any delays between function executions and will convert the loop into a basic loop.\n
\n\n```python\n#caution: infinite loop\n@loopimer(every=0)\ndef test(loop,): \n print('loopimer')\ntest() \n```\n\n\nThe first variable passed to the target function allows you to control the loop running in the background (called 'loop' in the examples on this page). You can choose any name for this variable, but it is important that you pass a variable name as a placeholder to the target function when declaring your desired function. The first variable name passed to your target function during declaration will always be reserved for the loop that will be running in the background. Upon calling the target function, this placeholder will be linked to the related thread controlling the loop.\n
\n\n\nThe loop starts authomatically when the function is called and will run indefinity. You can control the loop and how the function is executed using the placeholder variable. This is currently only possible when declaring the target function.\n
\n\nStopping the loop\n```python\n@loopimer(every=5)\ndef test(loop,): \n print('loopimer')\n loop.kill()\ntest() \n```\n\n \nPlease note that when calling the target function we don't pass the placeholder variable name to the function.\n \n
\n\nStopping the loop using loop counter\n\n It is important to note that the counter starts at 1 instead of 0.\n
\n\n```python\n@loopimer(every=1)\ndef test(loop,):\n print(loop.counter)\n if(loop.counter==10):\n print('loopimer')\n loop.kill()\ntest() \n```\n\nStopping the loop using loop elapsed time\n```python\n@loopimer(every=1)\ndef test(loop,):\n print(loop.elapsed,loop.total_seconds)\n if(loop.total_seconds>=6):\n print('loopimer')\n loop.kill()\ntest() \n```\n\nAdding custom variables to the loop\n\nThe loop placeholder variable is an open class and you can add new attributes to it. However, it is important to use attribute names that don't cause a naming conflict with names already being used by the class.\n
\n\n\nAttributes can be created inside the function or passed to the decorator instead.\n
\n\n```python\nfrom random import randrange\n\n@loopimer(every=1,i=0)\ndef test(loop,):\n print(loop.i)\n if(loop.i==10):\n print('loopimer')\n loop.kill()\n loop.i+=1\ntest()\n```\n\n```python\n@loopimer(every=1)\ndef test(loop,):\n loop.k=randrange(100)\n print(loop.k)\n if(loop.k>80):\n loop.kill()\ntest() \n```\n\nChanging the value of 'every' in the loop function\n\nThe 'every' variable passed through the decorator is available to the loop. You can change the value of this variable using 'loop.every'.\n
\n\n```python\n@loopimer(every=1)\ndef do(loop):\n print(loop.counter)\n if(loop.counter>10):\n loop.every=5\n if(loop.counter>20):\n loop.kill()\ndo() \n```\n\nUsing queue\n\nA sliceable variable can be passed to the loopimer decorator through the 'target' variable for processing. This sliceable variable is then split into slices of 'n_splits' size. The slices are placed in a queue and can be accessed through the 'sequence' attribute of the loop (loop.squence). This attribute is an instance of Queue. The loop automatically stops when no items are left in the queue.\n
\n\n\n When a target is not provided the queue is automatically filled with one item containing a zero. This means that the loop will stop after one cycle if the queue is accessed.
\n\n```python\n@loopimer(every=1)\ndef test(loop,):\n print(loop.counter,loop.sequence.get())\ntest() \n```\nUsing queue with target and n_splits\n```python\ntarget=[i for i in range(0,100,1)]\nn_splits=10 \n\n@loopimer(target=target,n_splits=n_splits,every=1)\ndef test(loop,):\n print(loop.sequence.get())\ntest() \n```\n\nUsing queue without providing target and n_splits to decorator\n```python\nimport queue\n\nnew_queue=queue.Queue()\nnew_target=[1,2,3,4,5,6,7,8,9]\nfor item in new_target:\n new_queue.put(item)\n \n@loopimer(every=1)\ndef test(loop,new_queue):\n if(loop.counter==1):\n loop.sequence=new_queue\n else:\n print(loop.counter,loop.sequence.get())\ntest(new_queue=new_queue) \n```\n\n```python\nimport queue\n\nnew_queue=queue.Queue()\nnew_target=[1,2,3,4,5,6,7,8,9]\nfor item in new_target:\n new_queue.put(item)\n \n@loopimer(every=1,new_queue=new_queue)\ndef test(loop,):\n if(loop.counter==1):\n loop.sequence=new_queue\n else:\n print(loop.counter,loop.sequence.get())\ntest()\n\n```\n\n\n```python\nimport queue\n\n@loopimer(every=1)\ndef test(loop):\n if(loop.counter==1):\n items=[1,2,3,4,5,6]\n loop.sequence=queue.Queue()\n for item in items:\n loop.sequence.put(item)\n else:\n print(loop.counter,loop.sequence.get())\ntest() \n```\n\nAdding your own queue variable to the loop\n\n```python\nimport queue\n\n@loopimer(every=1)\ndef test(loop):\n if(loop.counter==1):\n items=[1,2,3,4,5,6]\n loop.my_queue=queue.Queue()\n for item in items:\n loop.my_queue.put(item)\n \n else:\n print(loop.counter,loop.my_queue.get())\n if(loop.my_queue.qsize()==0):\n loop.kill()\ntest() \n\n```\n\nUsing time delays\n\n By Changing the value of the loop's pause attribute you can introduce time delays. This is especially useful when you reach a rate limit when pulling/pushing data from/to an API. \n
\n \n```python\n\ntarget=[i for i in range(0,100,1)]\nn_splits=10\n\n@loopimer(target=target,n_splits=n_splits,every=1)\ndef test(loop,):\n print(loop.sequence.qsize(),loop.sequence.get())\n if(loop.sequence.qsize()==8):\n loop.pause=20\ntest() \n```\n\n\n\n\n\nUsing queue and json\n```python\nimport numpy as np\nimport pandas as pd\nimport datetime as dt\nimport simplejson as json\n\ndf = pd.DataFrame(np.random.randint(0,100,size=(100, 4)), columns=list('ABCD'))\ndf['date']=dt.datetime.now()\n\ndf_json=json.loads(df.to_json(orient='records'))\n\n@loopimer(target=df_json,n_splits=10,every=1)\ndef test(loop,):\n print(json.dumps(loop.sequence.get()),'\\n')\ntest() \n```\n\nWithout using the loopimer decorator\n\n```python\ndef test(loop,):\n print(loop.counter)\n if(loop.counter==10):\n print('loopimer')\n loop.kill() \n\nx=[i for i in range(0,10000,1)]\nloop=loopi(target=x,)\nloop.apply_to(test,)\nloop.startTimedLoop(every=1)\n\n```\n\n```python\ndef test(loop,t):\n print(loop.counter+t)\n if(loop.counter==10):\n print('loopimer')\n loop.kill() \n\nx=[i for i in range(0,10000,1)]\nloop=loopi(target=x,)\nloop.apply_to(test,t=2)\nloop.startTimedLoop(every=1)\n```", "description_content_type": "text/markdown", "docs_url": null, "download_url": "https://github.com/rouzbeh-afrasiabi/loopimer/archive/v.1.0.2.tar.gz", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/rouzbeh-afrasiabi/loopimer", "keywords": "time,loop,control,threading,function", "license": "", "maintainer": "", "maintainer_email": "", "name": "loopimer", "package_url": "https://pypi.org/project/loopimer/", "platform": "", "project_url": "https://pypi.org/project/loopimer/", "project_urls": { "Download": "https://github.com/rouzbeh-afrasiabi/loopimer/archive/v.1.0.2.tar.gz", "Homepage": "https://github.com/rouzbeh-afrasiabi/loopimer" }, "release_url": "https://pypi.org/project/loopimer/1.0.2/", "requires_dist": null, "requires_python": "", "summary": "Package for time-controlled consecutive execution of a function using threading.", "version": "1.0.2" }, "last_serial": 5577762, "releases": { "1.0.1": [ { "comment_text": "", "digests": { "md5": "acf85b9a73d3c6c750c62a17a48eab8f", "sha256": "d7079a38eaa3b6d1cfde45affd7d8d45d64b5a149ebc2ab087423c896ae54d60" }, "downloads": -1, "filename": "loopimer-1.0.1.tar.gz", "has_sig": false, "md5_digest": "acf85b9a73d3c6c750c62a17a48eab8f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5585, "upload_time": "2019-07-19T12:21:13", "url": "https://files.pythonhosted.org/packages/bc/00/aa683f9273ee15611695a3e6d8eeb05ce7f10d71594dc3081a11cfba9cfb/loopimer-1.0.1.tar.gz" } ], "1.0.2": [ { "comment_text": "", "digests": { "md5": "40ddf3e4b0573027aa99cc1ecb64b843", "sha256": "2e6d0c9ae46a25eca75d78c6539d14482e7f975755a0fd9d3094fd069626a231" }, "downloads": -1, "filename": "loopimer-1.0.2.tar.gz", "has_sig": false, "md5_digest": "40ddf3e4b0573027aa99cc1ecb64b843", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5918, "upload_time": "2019-07-24T14:01:05", "url": "https://files.pythonhosted.org/packages/13/40/dacc6c1da2583cc8f486786a8461365a869c416a9b62e71c53bc61dbf3e2/loopimer-1.0.2.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "40ddf3e4b0573027aa99cc1ecb64b843", "sha256": "2e6d0c9ae46a25eca75d78c6539d14482e7f975755a0fd9d3094fd069626a231" }, "downloads": -1, "filename": "loopimer-1.0.2.tar.gz", "has_sig": false, "md5_digest": "40ddf3e4b0573027aa99cc1ecb64b843", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5918, "upload_time": "2019-07-24T14:01:05", "url": "https://files.pythonhosted.org/packages/13/40/dacc6c1da2583cc8f486786a8461365a869c416a9b62e71c53bc61dbf3e2/loopimer-1.0.2.tar.gz" } ] }