{ "info": { "author": "Ahmet Demir", "author_email": "me@ahmet2mir.eu", "bugtrack_url": null, "classifiers": [ "Development Status :: 2 - Pre-Alpha", "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Topic :: Software Development :: Build Tools" ], "description": "# Artron - multiprocess execution helper\n\n[![image](https://img.shields.io/pypi/l/artron.svg)](https://python.org/pypi/artron)\n[![image](https://img.shields.io/pypi/pyversions/artron.svg)](https://python.org/pypi/artron)\n[![Build Status](https://travis-ci.org/ahmet2mir/python-artron.svg?branch=master)](https://travis-ci.org/ahmet2mir/python-artron)\n\n`Artron` is a simple `python` module to use `multiprocessing` with dependency graph and queue management allowing easy tool creation.\n\n## Installation\n\npip\n\n pip install artron\n\n## Simple example\n\n> see examples/basic.py to get the full file\n\nFirst create an class with all actions needed inside (you could also use a module). `Artron` will use `getattr` on the object or module to run the task.\n\n```python\nimport time\n\nclass Builder(object):\n \n def builder_func_1(self, msg, retry):\n time.sleep(6)\n return \"builder_func_1 ==> \" + msg\n\n def builder_func_2(self, msg, retry):\n time.sleep(3)\n return \"builder_func_2 ==> \" + msg\n\n def builder_func_3(self, msg, retry):\n time.sleep(1)\n raise Exception(\"ERROR builder_func_3\")\n return \"builder_func_3 ==> \" + msg\n\n def builder_func_4(self, msg, retry):\n time.sleep(4)\n return \"builder_func_4 ==> \" + msg\n```\n\nNow use with Artron\n\n```python\nimport sys\nfrom pprint import pprint\nfrom artron.task import Task\nfrom artron.manager import Manager\n\ndef process(run=True):\n # builder to pass to Artron\n builder = Builder()\n\n # declare manager\n manager = Manager(builder, max_retry=2)\n\n # declare tasks\n task1 = Task('task-id-1', {'msg': 'task-1-msg'}, 'builder_func_1')\n task2 = Task('task-id-2', {'msg': 'task-2-msg'}, 'builder_func_2')\n task3 = Task('task-id-3', {'msg': 'task-3-msg'}, 'builder_func_3')\n task4 = Task('task-id-4', {'msg': 'task-4-msg'}, 'builder_func_4')\n task5 = Task('task-id-5', {'msg': 'task-5-msg'}, 'builder_func_2')\n task6 = Task('task-id-6', {'msg': 'task-6-msg'}, 'builder_func_4')\n \n # generate dependencies\n task1.add_require(task2.tid)\n task1.add_require(task3.tid)\n task1.add_require(task4.tid)\n task2.add_require(task4.tid)\n task6.add_require(task2.tid)\n task5.add_require(task1.tid)\n \n # add task\n manager.add(task1)\n manager.add(task2)\n manager.add(task3)\n manager.add(task4)\n manager.add(task5)\n manager.add(task6)\n\n # if we should run\n if run:\n # start\n results = manager.start()\n pprint(results)\n sys.exit(results['exit_code'])\n # otherwise print tasks ids\n else:\n for task in manager.tasks.keys():\n print(\"-\", task)\n\nif __name__ == '__main__':\n process()\n```\n\nThat's it!\n\n**Result**\n\n```shell\nartron: [ERROR] Traceback (most recent call last):\n File \"/home/ahmet/workspaces/devs/python-artron/artron/task.py\", line 89, in run\n **self.inputs\n File \"examples/basic.py\", line 19, in builder_func_3\n raise Exception(\"ERROR builder_func_3\")\nException: ERROR builder_func_3\n\nartron: [ERROR] ERROR builder_func_3\nartron: [ERROR] Traceback (most recent call last):\n File \"/home/ahmet/workspaces/devs/python-artron/artron/task.py\", line 89, in run\n **self.inputs\n File \"examples/basic.py\", line 19, in builder_func_3\n raise Exception(\"ERROR builder_func_3\")\nException: ERROR builder_func_3\n\nartron: [ERROR] ERROR builder_func_3\n{'date_end': '2018-08-29T20:02:54.640Z',\n 'date_start': '2018-08-29T20:02:39.606Z',\n 'elapsed': '00:00:15',\n 'exit_code': 1,\n 'results': {'aborted': 0,\n 'deps': 2,\n 'failures': 1,\n 'nrun': 0,\n 'ready': 0,\n 'success': 3},\n 'tasks': [{'date_created': '2018-08-29T20:02:39.605Z',\n 'date_end': None,\n 'date_start': None,\n 'func': 'builder_func_1',\n 'inputs': {'msg': 'task-1-msg'},\n 'require': ['task-id-2', 'task-id-4'],\n 'results': None,\n 'state': -2,\n 'tid': 'task-id-1',\n 'time_duration': 0.0,\n 'time_duration_str': '00:00:00'},\n {'date_created': '2018-08-29T20:02:39.605Z',\n 'date_end': '2018-08-29T20:02:41.617Z',\n 'date_start': '2018-08-29T20:02:40.615Z',\n 'func': 'builder_func_3',\n 'inputs': {'msg': 'task-3-msg'},\n 'require': [],\n 'results': 'ERROR builder_func_3',\n 'state': -1,\n 'tid': 'task-id-3',\n 'time_duration': 1.0019969940185547,\n 'time_duration_str': '00:00:01'},\n {'date_created': '2018-08-29T20:02:39.605Z',\n 'date_end': '2018-08-29T20:02:48.625Z',\n 'date_start': '2018-08-29T20:02:45.621Z',\n 'func': 'builder_func_2',\n 'inputs': {'msg': 'task-2-msg'},\n 'require': [],\n 'results': 'builder_func_2 ==> task-2-msg',\n 'state': 3,\n 'tid': 'task-id-2',\n 'time_duration': 3.0032620429992676,\n 'time_duration_str': '00:00:03'},\n {'date_created': '2018-08-29T20:02:39.605Z',\n 'date_end': None,\n 'date_start': None,\n 'func': 'builder_func_2',\n 'inputs': {'msg': 'task-5-msg'},\n 'require': [],\n 'results': None,\n 'state': -2,\n 'tid': 'task-id-5',\n 'time_duration': 0.0,\n 'time_duration_str': '00:00:00'},\n {'date_created': '2018-08-29T20:02:39.605Z',\n 'date_end': '2018-08-29T20:02:43.616Z',\n 'date_start': '2018-08-29T20:02:39.613Z',\n 'func': 'builder_func_4',\n 'inputs': {'msg': 'task-4-msg'},\n 'require': [],\n 'results': 'builder_func_4 ==> task-4-msg',\n 'state': 3,\n 'tid': 'task-id-4',\n 'time_duration': 4.003551006317139,\n 'time_duration_str': '00:00:04'},\n {'date_created': '2018-08-29T20:02:39.605Z',\n 'date_end': '2018-08-29T20:02:54.636Z',\n 'date_start': '2018-08-29T20:02:50.631Z',\n 'func': 'builder_func_4',\n 'inputs': {'msg': 'task-6-msg'},\n 'require': [],\n 'results': 'builder_func_4 ==> task-6-msg',\n 'state': 3,\n 'tid': 'task-id-6',\n 'time_duration': 4.00443696975708,\n 'time_duration_str': '00:00:04'}]}\n```\n\n## Details\n\n### Tasks\n\n`Task` is an object with `function` to run on `builder`, `inputs` to send and `state` also with time informations.\n\n**States values:**\n\n* -2: dependency error, means that parent task failed.\n* -1: task failed to run\n* 0: initial state (when creating them)\n* 1: task is ready and in queue, there is no more dependencies, waiting to be process by workers\n* 2: task is running\n* 3: task run successfully\n\n### Worker\n\n`Worker` is just a `process`. \nBy default, `multiprocessing.cpu_count()` is used as number of workers.\n\n## Integrations\n\nYou could use [click](http://click.pocoo.org/5/) to create simple cli.\n\n```shell\npip install click\n```\n\n```python\n# -*- coding: utf-8 -*-\nimport basic # import examples/basic.py\n\nimport click\n\n@click.group()\n@click.version_option()\ndef cli():\n \"\"\"Artron CLI\"\"\"\n\n@cli.command()\ndef start():\n \"\"\"Start all tasks.\"\"\"\n basic.process()\n\n@cli.command()\ndef list():\n \"\"\"List tasks.\"\"\"\n basic.process(False)\n\nif __name__ == '__main__':\n cli()\n```\n\nList tasks\n\n```shell\n$ python examples/basic_cli.py list\n- task-id-1\n- task-id-3\n- task-id-2\n- task-id-5\n- task-id-4\n- task-id-6\n```\n\n# Licence\n\nCopyright 2018 - Ahmet Demir\n\nLicensed under the Apache License, Version 2.0 (the \"License\"); you may not use this file except in compliance with the License. You may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.\n\n\nclass ProgressBar(object):\n \"\"\"Simple progress bar\"\"\"\n def __init__(self, total=100):\n self.total = total\n self.n = 0\n\n def update(self, count=1):\n if self.n == 0:\n sys.stdout.write(\"[%s]\" % (\" \" * self.total))\n sys.stdout.flush()\n sys.stdout.write(\"\\b\" * (self.total+1))\n for _ in range(0, min(count, self.total-self.n)):\n sys.stdout.write(\"-\")\n sys.stdout.flush()\n self.n += count\n\n def close(self):\n self.update(self.total - self.n)\n sys.stdout.write(\"\\n\")", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/ahmet2mir/python-artron.git", "keywords": "artron,multiprocessing,parallel", "license": "Apache 2.0", "maintainer": "", "maintainer_email": "", "name": "artron", "package_url": "https://pypi.org/project/artron/", "platform": "", "project_url": "https://pypi.org/project/artron/", "project_urls": { "Homepage": "https://github.com/ahmet2mir/python-artron.git" }, "release_url": "https://pypi.org/project/artron/0.0.5/", "requires_dist": null, "requires_python": ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*", "summary": "Artron - multiprocessing with dependency graph and queue management allowing easy tool creation.", "version": "0.0.5" }, "last_serial": 4413143, "releases": { "0.0.1": [ { "comment_text": "", "digests": { "md5": "272c68ce5ece391dd870c8ee8b47646a", "sha256": "c13151a9ec588b8f89c590482b4b4ba2869d71cc98f3c69bd61b6572dd58e321" }, "downloads": -1, "filename": "artron-0.0.1.tar.gz", "has_sig": false, "md5_digest": "272c68ce5ece391dd870c8ee8b47646a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10834, "upload_time": "2018-08-30T22:26:42", "url": "https://files.pythonhosted.org/packages/d7/24/dd471a900258ea0b5b0e13c6755e8b555109f0ecce0e0f6f6ef688fabe9f/artron-0.0.1.tar.gz" } ], "0.0.3": [ { "comment_text": "", "digests": { "md5": "c8cf6698376104ad716e15fa026acfff", "sha256": "0a1be48a9fd4bef922cfa5ec6df3163953fe6af4763a78d678661cde0558572b" }, "downloads": -1, "filename": "artron-0.0.3.tar.gz", "has_sig": false, "md5_digest": "c8cf6698376104ad716e15fa026acfff", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11735, "upload_time": "2018-10-25T00:07:21", "url": "https://files.pythonhosted.org/packages/bf/65/24e6cafc4c04cdff7be29b34ba2e3c911bc96a8f6a2ae486e4d84b075d62/artron-0.0.3.tar.gz" } ], "0.0.4": [ { "comment_text": "", "digests": { "md5": "45b5937562d4d587f088118e7cfc69ee", "sha256": "e4693292ab4fcf17390f84ad322e0ba0fc9c0f1f7ba5582a07c99fac268083fc" }, "downloads": -1, "filename": "artron-0.0.4.tar.gz", "has_sig": false, "md5_digest": "45b5937562d4d587f088118e7cfc69ee", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12007, "upload_time": "2018-10-25T00:18:15", "url": "https://files.pythonhosted.org/packages/37/ec/74ff7c93bf86496e4c3141f12607bdf4de2acaaee1481771a1814e5605a5/artron-0.0.4.tar.gz" } ], "0.0.5": [ { "comment_text": "", "digests": { "md5": "51cf8833050d6df29713fa5880c43703", "sha256": "d0f0cfb1d041f49b54f1e75abd02c01d07da0f9c92abc164768c1f5b86797d4a" }, "downloads": -1, "filename": "artron-0.0.5.tar.gz", "has_sig": false, "md5_digest": "51cf8833050d6df29713fa5880c43703", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*", "size": 12072, "upload_time": "2018-10-25T00:24:21", "url": "https://files.pythonhosted.org/packages/e1/77/35c4e06c60e83ca5cfec651be86dc47bc47b1814de64215c24124f5f57b2/artron-0.0.5.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "51cf8833050d6df29713fa5880c43703", "sha256": "d0f0cfb1d041f49b54f1e75abd02c01d07da0f9c92abc164768c1f5b86797d4a" }, "downloads": -1, "filename": "artron-0.0.5.tar.gz", "has_sig": false, "md5_digest": "51cf8833050d6df29713fa5880c43703", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*", "size": 12072, "upload_time": "2018-10-25T00:24:21", "url": "https://files.pythonhosted.org/packages/e1/77/35c4e06c60e83ca5cfec651be86dc47bc47b1814de64215c24124f5f57b2/artron-0.0.5.tar.gz" } ] }