{"id":21858233,"url":"https://github.com/simpleart/aio-stdout","last_synced_at":"2026-02-03T05:02:18.739Z","repository":{"id":57409151,"uuid":"453486116","full_name":"SimpleArt/aio-stdout","owner":"SimpleArt","description":"Asynchronous Input Output","archived":false,"fork":false,"pushed_at":"2023-01-05T23:15:03.000Z","size":30,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-12-22T01:41:37.180Z","etag":null,"topics":["asyncio","input-output","python3"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SimpleArt.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-01-29T18:36:57.000Z","updated_at":"2024-12-30T22:26:40.000Z","dependencies_parsed_at":"2023-02-04T23:02:13.958Z","dependency_job_id":null,"html_url":"https://github.com/SimpleArt/aio-stdout","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/SimpleArt/aio-stdout","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SimpleArt%2Faio-stdout","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SimpleArt%2Faio-stdout/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SimpleArt%2Faio-stdout/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SimpleArt%2Faio-stdout/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SimpleArt","download_url":"https://codeload.github.com/SimpleArt/aio-stdout/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SimpleArt%2Faio-stdout/sbom","scorecard":{"id":130276,"data":{"date":"2025-08-11","repo":{"name":"github.com/SimpleArt/aio-stdout","commit":"6079ccc87a51473c6156ede4aba924d7e902d257"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Code-Review","score":0,"reason":"Found 0/20 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}}]},"last_synced_at":"2025-08-16T05:07:30.378Z","repository_id":57409151,"created_at":"2025-08-16T05:07:30.388Z","updated_at":"2025-08-16T05:07:30.388Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29033716,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-03T02:28:16.591Z","status":"ssl_error","status_checked_at":"2026-02-03T02:27:48.904Z","response_time":96,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["asyncio","input-output","python3"],"created_at":"2024-11-28T02:44:26.380Z","updated_at":"2026-02-03T05:02:18.725Z","avatar_url":"https://github.com/SimpleArt.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# aio_stdout\n Asynchronous Input Output - Stdout\n\nThe purpose of this package is to provide asynchronous variants of the builtin `input` and `print` functions. `print` is known to be relatively slow compared to other operations. `input` is even slower because it has to wait for user input. While these slow IO operations are being ran, code using `asyncio` should be able to continuously run.\n\nPIP Installing\n---------------\n\nFor Unix/macOS:\n```\npython3 -m pip install aio-stdout\n```\n\nFor Windows:\n```\npy -m pip install aio-stdout\n```\n\nainput and aprint\n------------------\n\nWith `aio_stdout`, the `aio_stdout.ainput` and `aio_stdout.aprint` functions provide easy to use functionality with organized behaviour.\n\n```python\nimport asyncio\nfrom aio_stdout import ainput, aprint\n\nasync def countdown(n: int) -\u003e None:\n    \"\"\"Count down from `n`, taking `n` seconds to run.\"\"\"\n    for i in range(n, 0, -1):\n        await aprint(i)\n        await asyncio.sleep(1)\n\nasync def get_name() -\u003e str:\n    \"\"\"Ask the user for their name.\"\"\"\n    name = await ainput(\"What is your name? \")\n    await aprint(f\"Your name is {name}.\")\n    return name\n\nasync def main() -\u003e None:\n    await asyncio.gather(countdown(15), get_name())\n\nif __name__ == \"__main__\":\n    asyncio.run(main())\n```\n\nExample output:\n\n```\n15\nWhat is your name? Jane\n14\n13\n12\n11\n10\n9\n8\nYour name is Jane.\n7\n6\n5\n4\n3\n2\n1\n```\n\nNotice that while the prompt `\"What is your name? \"` is being waited for, the `countdown` continues to `aprint` in the background, without becoming blocked. The `countdown` does not, however, display its results until the `ainput` is completed. Instead it waits for the `ainput` to finish before flushing out all of the queued messages.\n\nIt is worth noting that with naive threading, a normal attempt to use `print` while waiting on an `input` leads to overlapping messages. Fixing this behavior requires a lot more work than should be needed to use a simple `print` or `input` function, which is why this package exists. To remedy this problem, queues are used to store messages until they are ready to be printed. \n\nIO Locks\n---------\n\nAlthough the asynchronization behaviors of `ainput` and `aprint` are nice, sometimes we want to be able to synchronize our messages even more. IO locks provide a way to group messages together, locking the global `aio_stdout` queues until it finishes or yields access.\n\n```python\nimport asyncio\nfrom aio_stdout import IOLock, ainput, aprint\n\nasync def countdown(n: int) -\u003e None:\n    \"\"\"Count down from `n`, taking `n` seconds to run.\"\"\"\n    async with IOLock(n=5) as lock:\n        for i in range(n, 0, -1):\n            await lock.aprint(i)\n            await asyncio.sleep(1)\n\nasync def get_name() -\u003e str:\n    \"\"\"Ask the user for their name.\"\"\"\n    async with IOLock() as lock:\n        name = await lock.ainput(\"What is your name? \")\n        await lock.aprint(f\"Your name is {name}.\")\n    return name\n\nasync def main() -\u003e None:\n    await asyncio.gather(countdown(15), get_name())\n\nif __name__ == \"__main__\":\n    asyncio.run(main())\n```\n\nLet's try the example again now using the new locks:\n\n```\n15\n14\n13\n12\n11\nWhat is your name? Jane\nYour name is Jane.\n10\n9\n8\n7\n6\n5\n4\n3\n2\n1\n```\n\nNotice that this time the `countdown` does not immediately yield to the `get_name`. Instead, it runs 5 messages before yielding control over to `get_name`. Now, after the `lock.ainput` finishes, it does not yield to `countdown`. Instead, it runs its own `lock.aprint` first. In the meantime, `countdown` continues to run in the background and flushes all of its buffered messages afterwards.\n\nFlushing\n---------\n\nSince messages may be delayed, it is possible for your asynchronous code to finish running before all messages are displayed, producing confusing results. As such, the best recommended practice is to flush from `main` before terminating.\n\n```python\nfrom aio_stdout import flush\n\n@flush\nasync def main() -\u003e None:\n    ...\n```\n\nFinal Example\n-------------\n\nCombining all best practices, the final example should look something like this:\n\n```python\nimport asyncio\nfrom aio_stdout import IOLock, ainput, aprint, flush\n\nasync def countdown(n: int) -\u003e None:\n    \"\"\"Count down from `n`, taking `n` seconds to run.\"\"\"\n    for i in range(n, 0, -1):\n        await aprint(i)\n        await asyncio.sleep(1)\n\nasync def get_name() -\u003e str:\n    \"\"\"Ask the user for their name.\"\"\"\n    async with IOLock() as lock:\n        name = await lock.ainput(\"What is your name? \")\n        await lock.aprint(f\"Your name is {name}.\")\n    return name\n\n@flush\nasync def main() -\u003e None:\n    await asyncio.gather(countdown(15), get_name())\n\nif __name__ == \"__main__\":\n    asyncio.run(main())\n```\n\nCommon Gotchas\n---------------\n\n- Using `input` or `print` instead of `ainput` and `aprint` will push a message immediately to the console, potentially conflicting with `ainput` or `aprint`.\n- Using `ainput` or `aprint` instead of `lock.ainput` and `lock.aprint` may produce **deadlock** due to having to wait for the lock to release. As such, the `lock` is equipped with a default `timeout` limit of 10 seconds to avoid deadlock and explain to users this potential problem.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimpleart%2Faio-stdout","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsimpleart%2Faio-stdout","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimpleart%2Faio-stdout/lists"}