├── .gitignore ├── LICENSE ├── PQI ├── __init__.py └── pqi.py ├── README.md ├── picture └── db.png ├── setup.cfg └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .coverage.* 42 | .cache 43 | nosetests.xml 44 | coverage.xml 45 | *,cover 46 | .hypothesis/ 47 | 48 | # Translations 49 | *.mo 50 | *.pot 51 | 52 | # Django stuff: 53 | *.log 54 | local_settings.py 55 | 56 | # Flask stuff: 57 | instance/ 58 | .webassets-cache 59 | 60 | # Scrapy stuff: 61 | .scrapy 62 | 63 | # Sphinx documentation 64 | docs/_build/ 65 | 66 | # PyBuilder 67 | target/ 68 | 69 | # IPython Notebook 70 | .ipynb_checkpoints 71 | 72 | # pyenv 73 | .python-version 74 | 75 | # celery beat schedule file 76 | celerybeat-schedule 77 | 78 | # dotenv 79 | .env 80 | 81 | # virtualenv 82 | venv/ 83 | ENV/ 84 | 85 | # Spyder project settings 86 | .spyderproject 87 | 88 | # Rope project settings 89 | .ropeproject 90 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Yanghangfeng 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /PQI/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhangf/PyQuickInstall/03bf74e33950bde8feaf83e9a7ca16a6ec42d9ce/PQI/__init__.py -------------------------------------------------------------------------------- /PQI/pqi.py: -------------------------------------------------------------------------------- 1 | """PQI 2 | Usage: 3 | pqi ls 4 | pqi use 5 | pqi show 6 | pqi add 7 | pqi remove 8 | pqi (-h | --help) 9 | pqi (-v | --version) 10 | Options: 11 | -h --help Show this screen. 12 | -v --version Show version. 13 | """ 14 | """ 15 | _ __ _,.---._ .=-.-. 16 | .-`." ,`. ,-." - , `. /==/_ / 17 | /==/, - \/==/ , - \ |==|, | 18 | |==| _ .=. |==| - .=. , ||==| | 19 | |==| , "=",|==| : ;=: - ||==|- | 20 | |==|- ".."|==|, "=" , ||==| ,| 21 | |==|, | \==\ _ - ;|==|- | 22 | /==/ - | ".=". , ; -\/==/. / 23 | `--`---" `--`--"" `--`--`-` 24 | ---- A Terminal Tools For Python 25 | """ 26 | 27 | import os 28 | import re 29 | import sys 30 | import pickle 31 | import platform 32 | from docopt import docopt 33 | try: 34 | import configparser 35 | except: 36 | import ConfigParser as configparser 37 | 38 | FILE_NAME = "~\\pip\\pip.ini" if ("Windows" in platform.system()) else "~/.config/pip/pip.conf" 39 | FILE_PATH = os.path.expanduser(FILE_NAME) 40 | dir_path = os.path.dirname(FILE_PATH) 41 | if not os.path.exists(dir_path): 42 | os.makedirs(dir_path) 43 | SOURCES_NAME = os.path.join(dir_path, "sources.dict") 44 | SOURCES = dict() 45 | 46 | if not os.path.exists(SOURCES_NAME): 47 | with open(SOURCES_NAME, "wb") as fp: 48 | pickle.dump({ 49 | "pypi": "https://pypi.python.org/simple/", 50 | "tuna": "https://pypi.tuna.tsinghua.edu.cn/simple", 51 | "douban": "https://pypi.doubanio.com/simple/", 52 | "aliyun": "https://mirrors.aliyun.com/pypi/simple/", 53 | "ustc": "https://mirrors.ustc.edu.cn/pypi/web/simple" 54 | }, fp) 55 | with open(SOURCES_NAME, "rb") as fp: 56 | SOURCES = pickle.load(fp) 57 | 58 | APP_DESC = """ 59 | PQI 60 | ---- A Terminal Tools For Python 61 | @author Hangfeng Yang (https:/github.com/yhangf) 62 | last_update 2023-04-10 19:27 63 | """ 64 | 65 | def list_all_source(): 66 | print('\n') 67 | for key in SOURCES.keys(): 68 | print(key, '\t', SOURCES[key]) 69 | print('\n') 70 | 71 | def write_file(source_name): 72 | with open(FILE_PATH, 'w') as fp: 73 | str_ = "[global]\nindex-url = {0}\n[install]\ntrusted-host = {1}".format( 74 | SOURCES[source_name], SOURCES[source_name].split('/')[2]) 75 | fp.write(str_) 76 | 77 | def select_source_name(source_name): 78 | if source_name not in SOURCES.keys(): 79 | print("\n{} is not in the Source list.\n".format(source_name)) 80 | else: 81 | write_file(source_name) 82 | print("\nSource is changed to {}({}).\n".format(source_name, SOURCES[source_name])) 83 | 84 | def show_current_source(): 85 | if not os.path.exists(FILE_PATH): 86 | print("\nCurrent source is pypi.\n") 87 | return 88 | config = configparser.ConfigParser() 89 | config.read(FILE_PATH) 90 | index_url = config.get("global", "index-url") 91 | for key in SOURCES.keys(): 92 | if index_url == SOURCES[key]: 93 | print("\nCurrent source is {}({}).\n".format(key, index_url)) 94 | break 95 | else: 96 | print("\nCurrent source is {}.\n".format(index_url)) 97 | 98 | def check_url(url): 99 | p = re.compile("^https?://.+?/simple/?$") 100 | if p.match(url) == None: 101 | return False 102 | return True 103 | 104 | def add_source(source_name, source_url): 105 | if not check_url(source_url): 106 | print("\nURL({}) does not conform to the rules.\n".format(source_url)) 107 | return 108 | SOURCES[source_name] = source_url 109 | with open(SOURCES_NAME, "wb") as fp: 110 | pickle.dump(SOURCES, fp) 111 | print("\n{}({}) is add to Source list.\n".format(source_name, source_url)) 112 | 113 | def remove_source(source_name): 114 | if source_name not in SOURCES.keys(): 115 | print("\n{} is not in the Source list.\n".format(source_name)) 116 | else: 117 | source_url = SOURCES.pop(source_name) 118 | with open(SOURCES_NAME, "wb") as fp: 119 | pickle.dump(SOURCES, fp) 120 | print("\n{}({}) is remove to Source list.\n".format(source_name, source_url)) 121 | 122 | def main(): 123 | arguments = docopt(__doc__, version="3.0.0") 124 | if arguments["ls"]: 125 | list_all_source() 126 | elif arguments["use"]: 127 | select_source_name(arguments[""]) 128 | elif arguments["show"]: 129 | show_current_source() 130 | elif arguments["add"]: 131 | add_source(arguments[""], arguments[""]) 132 | elif arguments["remove"]: 133 | remove_source(arguments[""]) 134 | else: 135 | print("input error!") 136 | 137 | if __name__ == "__main__": 138 | print(APP_DESC) 139 | main() 140 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ```shell 2 | _ __ _,.---._ .=-.-. 3 | .-`.' ,`. ,-.' - , `. /==/_ / 4 | /==/, - \/==/ , - \ |==|, | 5 | |==| _ .=. |==| - .=. , ||==| | 6 | |==| , '=',|==| : ;=: - ||==|- | 7 | |==|- '..'|==|, '=' , ||==| ,| 8 | |==|, | \==\ _ - ;|==|- | 9 | /==/ - | '.='. , ; -\/==/. / 10 | `--`---' `--`--'' `--`--`-` 11 | 12 | ---- by Hangfeng Yang 13 | 14 | ``` 15 | #

pqi: a terminal tools for Python:globe_with_meridians:

16 | 17 |

18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 |

34 | 由于国内通过pip下载python包的速度真的很慢,很容易因为超时而失败,而pqi可以把PyPi源迅速切换为国内源tuna, douban, aliyun, ustc从而大大加快python包的安装速度,提速效果见下图所示。 35 | 36 | ![](https://github.com/yhangf/PyQuickInstall/blob/master/picture/db.png) 37 | 38 | ## 怎么使用(兼容py2/py3/linux/windows/MacOS) 39 | 40 | ### 1.安装 41 | #### 方法一(推荐) 42 | 43 | ``` 44 | >>> pip install pqi 45 | ``` 46 | 47 | #### 方法二 48 | ``` 49 | >>> git clone https://github.com/yhangf/PyQuickInstall.git 50 | >>> python3 setup.py install 51 | ``` 52 | 53 | 54 | ### 2. 命令行输入 `pqi` 回车 55 | ``` 56 | >>> pqi 57 | Usage: 58 | pqi ls 59 | pqi use 60 | pqi show 61 | pqi add 62 | pqi remove 63 | pqi (-h | --help) 64 | pqi (-v | --version) 65 | Options: 66 | -h --help Show this screen. 67 | -v --version Show version. 68 | ``` 69 | * 列举所有支持的PyPi源 70 | ``` 71 | >>> pqi ls 72 | ``` 73 | 74 | * 改变PyPi源 75 | ``` 76 | >>> pqi use 77 | ``` 78 | 例子,比如运行`pqi use tuna`即把当前PyPi源改为清华的PyPi源 79 | 80 | * 显示当前PyPi源 81 | ``` 82 | >>> pqi show 83 | ``` 84 | 85 | * 添加新的pip源(如添加USTC源) 86 | ``` 87 | >>> pqi add ustc https://mirrors.ustc.edu.cn/pypi/web/simple 88 | ``` 89 | 90 | * 移除pip源(如官方PyPi源) 91 | ``` 92 | >>> pqi remove pypi 93 | ``` 94 | 95 | ### 3. 升级到最新版`pqi` 96 | ``` 97 | >>> pip install --upgrade pqi 98 | ``` 99 | 100 | ## LICENSE 101 | [MIT](https://github.com/yhangf/PyQuickInstall/blob/master/LICENSE) 102 | -------------------------------------------------------------------------------- /picture/db.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhangf/PyQuickInstall/03bf74e33950bde8feaf83e9a7ca16a6ec42d9ce/picture/db.png -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | desciption_file = README.md 3 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup, find_packages 2 | 3 | VERSION = '4.0.2' 4 | 5 | with open("README.md", "r", encoding="utf-8") as fp: 6 | long_description = fp.read() 7 | 8 | setup(name='pqi', 9 | version=VERSION, 10 | description="Fast switching PyPi mirror image source", 11 | classifiers=[], # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers 12 | keywords='python、PyPi source、terminal', 13 | author='HangfengYang', 14 | author_email='yhf5fhy@gmail.com', 15 | url='https://github.com/yhangf/PyQuickInstall', 16 | license='MIT', 17 | packages=["PQI"], 18 | long_description=long_description, 19 | long_description_content_type="text/markdown", 20 | include_package_data=True, 21 | zip_safe=True, 22 | install_requires=[ 23 | 'docopt', 24 | ], 25 | entry_points={ 26 | 'console_scripts':[ 27 | 'pqi = PQI.pqi:main' 28 | ] 29 | }, 30 | ) 31 | --------------------------------------------------------------------------------