{ "info": { "author": "Ben Woodcroft", "author_email": "donttrustben@gmail.com", "bugtrack_url": null, "classifiers": [], "description": "Extern\n=================\n\nExtern is an opinionated version of Python's `subprocess`, making it just that little\nbit more convenient to run shell commands from within Python code.\n\nIt is reasonably straightforward:\n```\n>>> import extern\n>>> extern.run(\"echo it works\") #=> returns 'it works\\n'\n>>> extern.run(\"echo 1 2 5 |cat\") #=> returns '1 2 5\\n'\n```\nWhen a command that fails is run e.g.\n```\n>>> extern.run(\"cat /not_a_file\")\nTraceback (most recent call last):\n File \"\", line 1, in \n File \"build/bdist.linux-x86_64/egg/extern/__init__.py\", line 29, in run\nextern.ExternCalledProcessError: Command cat /not_a_file returned non-zero exit status 1.\nSTDERR was: cat: /not_a_file: No such file or directory\nSTDOUT was: \n```\nan exception is raised just like `subprocess`. However, the error message\ngenerated includes STDERR and STDOUT, which is more convenient for debugging. For reference, the `subprocess` equivalent:\n```\n>>> subprocess.check_output(['bash','-c','cat /not_a_file'])\ncat: /not_a_file: No such file or directory\nTraceback (most recent call last):\n File \"\", line 1, in \n File \"/usr/lib/python2.7/subprocess.py\", line 573, in check_output\n raise CalledProcessError(retcode, cmd, output=output)\nsubprocess.CalledProcessError: Command '['bash', '-c', 'cat /not_a_file']' returned non-zero exit status 1\n```\nThe useful thing is that `Extern` collects STDERR and only reports it when there is a non-zero exit status, discarding it otherwise.\n\n**IMPORTANT**: use of this library with untrusted strings presents a security risk in the same way as [little bobby tables](http://xkcd.com/327/), and [shell=True](https://docs.python.org/2/library/subprocess.html#frequently-used-arguments) in `subprocess`.\n\n###Multiple commands run simultaneously\n```\n>>> extern.run_many(['echo once','echo twice','echo thrice'])\n#=> ['once\\n', 'twice\\n', 'thrice\\n']\n```\nProgress can also be observed:\n```\n>>> extern.run_many(['echo once','echo twice','echo thrice'], progress_stream=sys.stderr)\nFinished processing 3 of 3 (100.00%) items.\n#=> ['once\\n', 'twice\\n', 'thrice\\n']\n```\n`STDIN` can be provided to `run()`:\n```\nextern.run('cat',stdin='dog') #=> 'dog'\n````\n\n###Which\nThere is also a `which` function, useful for determing where (and if) a program\nexists on the command line:\n```\n>>> import extern\n>>> extern.which('cat') #=> '/bin/cat'\n>>> extern.which('dog') #=> None\n```\n\n\nInstallation\n--------------\nYou can also install it directly from the Python Package Index with this command:\n```\nsudo pip install extern\n```\n\nLicence\n--------\nSee file LICENCE.txt in this folder\n\nContribute\n-----------\nExtern is an open-source software. Everyone is welcome to contribute !\n", "description_content_type": null, "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "", "keywords": "", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "extern", "package_url": "https://pypi.org/project/extern/", "platform": "", "project_url": "https://pypi.org/project/extern/", "project_urls": null, "release_url": "https://pypi.org/project/extern/0.3.0/", "requires_dist": null, "requires_python": "", "summary": "", "version": "0.3.0" }, "last_serial": 3572041, "releases": { "0.0.3": [ { "comment_text": "", "digests": { "md5": "d9f1e9d2c9c221ab66b5e2f826b46aa9", "sha256": "ff5b65e25a1d4abce57955321a099d7e3754fce5acfe3ddd23995db89e843d2c" }, "downloads": -1, "filename": "extern-0.0.3.tar.gz", "has_sig": false, "md5_digest": "d9f1e9d2c9c221ab66b5e2f826b46aa9", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6651, "upload_time": "2015-08-03T06:13:06", "url": "https://files.pythonhosted.org/packages/af/9d/286c8464f9302b822cd3a64c2e6ea25b03dc83f0003084528b8d32f0d6e4/extern-0.0.3.tar.gz" } ], "0.0.4": [ { "comment_text": "", "digests": { "md5": "ab9745dbbbe9968953dd85a5709c3caf", "sha256": "5e960283e6715bc020ce9d2122cf8325bbe7e5a0a55280d3565ce901e76bffc7" }, "downloads": -1, "filename": "extern-0.0.4.tar.gz", "has_sig": false, "md5_digest": "ab9745dbbbe9968953dd85a5709c3caf", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6687, "upload_time": "2015-08-03T06:24:02", "url": "https://files.pythonhosted.org/packages/d8/c4/4769831c85c0c21536039fa0be86f6b87b0171e9fa9979faf4004719afa4/extern-0.0.4.tar.gz" } ], "0.1.0": [ { "comment_text": "", "digests": { "md5": "33e42793e0313ae08af70460ae73e101", "sha256": "427ab75f423ced0e30c67bd4c33bc42c70b2a29128d869e7fb2d7d6d4fd08539" }, "downloads": -1, "filename": "extern-0.1.0.tar.gz", "has_sig": false, "md5_digest": "33e42793e0313ae08af70460ae73e101", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8334, "upload_time": "2015-08-10T08:02:06", "url": "https://files.pythonhosted.org/packages/3d/33/c0a11b3ccf79e784a813bb52804c96d8ddb718f6f20379915e49279d9ef7/extern-0.1.0.tar.gz" } ], "0.2.0": [ { "comment_text": "", "digests": { "md5": "73566bd76b658322b1e67d3c9271264a", "sha256": "94fbf9e9d3d4780df08b9d7d8e1b14d594fb4ff9951505878ba06a2ae55b4007" }, "downloads": -1, "filename": "extern-0.2.0.tar.gz", "has_sig": false, "md5_digest": "73566bd76b658322b1e67d3c9271264a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8490, "upload_time": "2017-01-28T07:16:59", "url": "https://files.pythonhosted.org/packages/cd/13/f7390dac42f583bf9d24ec3e7f9634cd3ba749790ed9ff6475031f55e10a/extern-0.2.0.tar.gz" } ], "0.2.1": [ { "comment_text": "", "digests": { "md5": "093c4022301cc57eef0344c577088a09", "sha256": "b57b931031e0b07fbe54bcdc2ab9b61a47eb7e52e9373b9372045982780ee512" }, "downloads": -1, "filename": "extern-0.2.1.tar.gz", "has_sig": false, "md5_digest": "093c4022301cc57eef0344c577088a09", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8573, "upload_time": "2017-01-28T11:23:03", "url": "https://files.pythonhosted.org/packages/cf/86/c861f334f2af20a577348c3eb9e05b8d0bbf3a9b7a7126609541becd7033/extern-0.2.1.tar.gz" } ], "0.3.0": [ { "comment_text": "", "digests": { "md5": "77052f5c3c9f75e32169fe9a95a8031c", "sha256": "5a79f0e94110e8f6a0e9eb296b486e836198723fe231d6b342d2fc198221f411" }, "downloads": -1, "filename": "extern-0.3.0.tar.gz", "has_sig": false, "md5_digest": "77052f5c3c9f75e32169fe9a95a8031c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9916, "upload_time": "2018-02-11T13:17:11", "url": "https://files.pythonhosted.org/packages/db/ec/ea94159feeaec016dff083f74b8c6d8aeb703e8a7b3c23efe8cfc9db466a/extern-0.3.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "77052f5c3c9f75e32169fe9a95a8031c", "sha256": "5a79f0e94110e8f6a0e9eb296b486e836198723fe231d6b342d2fc198221f411" }, "downloads": -1, "filename": "extern-0.3.0.tar.gz", "has_sig": false, "md5_digest": "77052f5c3c9f75e32169fe9a95a8031c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9916, "upload_time": "2018-02-11T13:17:11", "url": "https://files.pythonhosted.org/packages/db/ec/ea94159feeaec016dff083f74b8c6d8aeb703e8a7b3c23efe8cfc9db466a/extern-0.3.0.tar.gz" } ] }