最近博主在折腾python调用nacos,这方面资料好少,还是java sdk多。。。一顿搜索过后发现了一个包:KcangNacos,看着还行倒腾了一会发现里面有些问题,就打算自己修复调整下并发布

cookiecutter

这是一个用来生成一个标准python package模板的工具,官网:https://cookiecutter-pypackage.readthedocs.io/en/latest/readme.html

安装

1
[root@jenkins-manager demo01]# pip install cookiecutter

使用模板生成一个package目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
[root@jenkins-manager demo01]# cookiecutter https://gitee.com/siq/cookiecutter-pypackage.git
/usr/local/lib/python3.6/site-packages/requests/__init__.py:104: RequestsDependencyWarning: urllib3 (1.26.12) or chardet (5.0.0)/charset_normalizer (2.0.12) doesn't match a supported version!
RequestsDependencyWarning)
You've downloaded /root/.cookiecutters/cookiecutter-pypackage before. Is it okay to delete and re-download it? [yes]:
full_name [Audrey Roy Greenfeld]: KONE-XAD
email [audreyr@example.com]: 1793360097@qq.com
github_username [audreyr]: KONE-XAD
project_name [Python Boilerplate]: xadnacos
project_slug [xadnacos]: xadnacos
project_short_description [Python Boilerplate contains all the boilerplate you need to create a Python package.]: python sdk for nacos
pypi_username [KONE-XAD]: xadocker
version [0.1.0]: 0.1.0
use_pytest [n]: n
use_pypi_deployment_with_travis [y]: n
add_pyup_badge [n]: n
Select command_line_interface:
1 - Click
2 - Argparse
3 - No command-line interface
Choose from 1, 2, 3 [1]: 1
create_author_file [y]: y
Select open_source_license:
1 - MIT license
2 - BSD license
3 - ISC license
4 - Apache Software License 2.0
5 - GNU General Public License v3
6 - Not open source
Choose from 1, 2, 3, 4, 5, 6 [1]: 1

此时目录会生成一个package目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@jenkins-manager demo01]# ll
total 0
drwxr-xr-x 6 root root 326 Feb 4 14:29 xadnacos
[root@jenkins-manager demo01]# ll xadnacos/
total 44
-rw-r--r-- 1 root root 151 Feb 4 14:29 AUTHORS.rst
-rw-r--r-- 1 root root 3536 Feb 4 14:29 CONTRIBUTING.rst
drwxr-xr-x 2 root root 191 Feb 4 14:29 docs
-rw-r--r-- 1 root root 89 Feb 4 14:29 HISTORY.rst
-rw-r--r-- 1 root root 1067 Feb 4 14:29 LICENSE
-rw-r--r-- 1 root root 2266 Feb 4 14:29 Makefile
-rw-r--r-- 1 root root 262 Feb 4 14:29 MANIFEST.in
-rw-r--r-- 1 root root 846 Feb 4 14:29 README.rst
-rw-r--r-- 1 root root 144 Feb 4 14:29 requirements_dev.txt
-rw-r--r-- 1 root root 392 Feb 4 14:29 setup.cfg
-rw-r--r-- 1 root root 1577 Feb 4 14:29 setup.py
drwxr-xr-x 2 root root 49 Feb 4 14:29 tests
-rw-r--r-- 1 root root 282 Feb 4 14:29 tox.ini
drwxr-xr-x 2 root root 58 Feb 4 14:29 xadnacos

编写package的功能

此时在xadnacos/xadnacos内编写你的功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 当前package目录结构
[root@jenkins-manager demo01]# tree
.
└── xadnacos
├── AUTHORS.rst
├── CONTRIBUTING.rst
├── docs
│   ├── authors.rst
│   ├── conf.py
│   ├── contributing.rst
│   ├── history.rst
│   ├── index.rst
│   ├── installation.rst
│   ├── make.bat
│   ├── Makefile
│   ├── readme.rst
│   └── usage.rst
├── HISTORY.rst
├── LICENSE
├── Makefile
├── MANIFEST.in
├── README.rst
├── requirements_dev.txt
├── setup.cfg
├── setup.py
├── tests
│   ├── __init__.py
│   └── test_xadnacos.py
├── tox.ini
└── xadnacos
├── cli.py
├── __init__.py
└── xadnacos.py

4 directories, 26 files

编写xadnacos.py内功能

参考KcangNacos调整修改:https://github.com/KcangYan/nacos-python-sdk.git

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
# 在原作者的nacos.py中服务注册漏了clusterName参数,导致所有服务都注册到默认集群中
[root@jenkins-manager demo01]# cat xadnacos/xadnacos/xadnacos.py
# -*- coding: utf-8 -*-
import requests,time
import hashlib
import urllib
import json

import logging

LOG_FORMAT = '%(asctime)s -%(name)s- %(threadName)s-%(thread)d - %(levelname)s - %(message)s'
DATE_FORMAT = "%m/%d/%Y %H:%M:%S %p"
#日志配置
logging.basicConfig(level=logging.INFO,format=LOG_FORMAT,datefmt=DATE_FORMAT)

import threading

class nacos:
def __init__(self,ip="127.0.0.1",port=8848):
self.ip = ip
self.port = port
self.__threadHealthyDict = {}
self.__configDict = {}
self.__registerDict = {}
self.healthy = ""

def __healthyCheckThreadRun(self):
while True:
time.sleep(5)
self.healthy = int(time.time())
#检查configThread
try:
for item in self.__configDict:
configMsg = item.split("\001")
dataId = configMsg[0]
group = configMsg[1]
tenant = configMsg[2]
x = int(time.time()) - self.__threadHealthyDict[dataId + group + tenant]
if (x > 50):
md5Content = configMsg[3]
myConfig = self.__configDict[item]
configThread = threading.Thread(target=self.__configListeningThreadRun,
args=(dataId, group, tenant, md5Content, myConfig))
self.__threadHealthyDict[dataId + group + tenant] = int(time.time())
configThread.start()
logging.info("配置信息监听线程重启成功: dataId=" + dataId + "; group=" + group + "; tenant=" + tenant)
except:
logging.exception("配置信息监听线程健康检查错误",exc_info=True)
#检查registerThread
try:
x = int(time.time()) - self.__registerDict["healthy"]
if (x > 15):
serviceIp = self.__registerDict["serviceIp"]
servicePort = self.__registerDict["servicePort"]
serviceName = self.__registerDict["serviceName"]
namespaceId = self.__registerDict["namespaceId"]
groupName = self.__registerDict["groupName"]
clusterName = self.__registerDict["clusterName"]
ephemeral = self.__registerDict["ephemeral"]
metadata = self.__registerDict["metadata"]
weight = self.__registerDict["weight"]
enabled = self.__registerDict["enabled"]
self.registerService(serviceIp,servicePort,serviceName,
namespaceId,groupName,clusterName,
ephemeral,metadata,weight,enabled)
except:
logging.exception("服务注册心跳进程健康检查失败",exc_info=True)

def healthyCheck(self):
t = threading.Thread(target=self.__healthyCheckThreadRun)
t.start()
logging.info("健康检查线程已启动")

def __configListeningThreadRun(self,dataId,group,tenant,md5Content,myConfig):
getConfigUrl = "http://" + self.ip + ":" + str(self.port) + "/nacos/v1/cs/configs"
params = {
"dataId": dataId,
"group": group,
"tenant": tenant
}

licenseConfigUrl = "http://" + self.ip + ":" + str(self.port) + "/nacos/v1/cs/configs/listener"
header = {"Long-Pulling-Timeout": "30000"}
while True:
self.__threadHealthyDict[dataId + group + tenant] = int(time.time())
if (tenant == "public"):
files = {"Listening-Configs": (None, dataId + "\002" + group + "\002" + md5Content + "\001")}
else:
files = {"Listening-Configs": (None, dataId + "\002" + group + "\002" + md5Content + "\002" + tenant + "\001")}
re = requests.post(licenseConfigUrl, files=files, headers=header)
if (re.text != ""):
try:
re = requests.get(getConfigUrl, params=params)
nacosJson = re.json()
md5 = hashlib.md5()
md5.update(re.content)
md5Content = md5.hexdigest()
for item in nacosJson:
myConfig[item] = nacosJson[item]
logging.info("配置信息更新成功: dataId=" + dataId + "; group=" + group + "; tenant=" + tenant)
except:
logging.exception("配置信息更新失败:dataId=" + dataId + "; group=" + group + "; tenant=" + tenant,
exc_info=True)
break

def config(self,myConfig,dataId,group="DEFAULT_GROUP",tenant="public"):
logging.info("正在获取配置: dataId="+dataId+"; group="+group+"; tenant="+tenant)
getConfigUrl = "http://" + self.ip + ":" + str(self.port) + "/nacos/v1/cs/configs"
params = {
"dataId": dataId,
"group": group,
"tenant": tenant
}
try:
re = requests.get(getConfigUrl, params=params)
nacosJson = re.json()
md5 = hashlib.md5()
md5.update(re.content)
md5Content = md5.hexdigest()

self.__configDict[dataId+"\001"+group+"\001"+tenant+"\001"+md5Content] = myConfig

for item in nacosJson:
myConfig[item] = nacosJson[item]
logging.info("配置获取成功:dataId="+dataId+"; group="+group+"; tenant="+tenant)
configThread = threading.Thread(target=self.__configListeningThreadRun,args=(dataId,group,tenant,md5Content,myConfig))
self.__threadHealthyDict[dataId+group+tenant] = int(time.time())
configThread.start()
except Exception:
logging.exception("配置获取失败:dataId="+dataId+"; group="+group+"; tenant="+tenant, exc_info=True)

def __registerBeatThreadRun(self,serviceIp,servicePort,serviceName,
groupName,namespaceId,metadata,weight,clusterName):

beatUrl = "http://" + self.ip + ":" + str(self.port) + "/nacos/v1/ns/instance/beat?"
beatJson = {
"ip": serviceIp,
"port": servicePort,
"serviceName": serviceName,
"metadata": metadata,
# "scheduled": "true",
"weight": weight
}
params_beat = {
"serviceName": serviceName,
"groupName": groupName,
"clusterName": clusterName,
"namespaceId": namespaceId,
"beat": urllib.request.quote(json.dumps(beatJson))
}
for item in params_beat:
beatUrl = beatUrl + item + "=" + params_beat[item] + "&"
while True:
self.__registerDict["healthy"] = int(time.time())
try:
time.sleep(5)
re = requests.put(beatUrl[:-1])
if(re.json()['code'] != 10200):
self.__registerDict["healthy"] = int(time.time())-10
logging.info(re.text)
break
except json.JSONDecodeError:
self.__registerDict["healthy"] = int(time.time()) - 10
break
except :
logging.exception("服务心跳维持失败!",exc_info=True)
break

def registerService(self,serviceIp,servicePort,serviceName,namespaceId="public",
groupName="DEFAULT_GROUP",clusterName="DEFAULT",
ephemeral=True,metadata={},weight=1,enabled=True):
self.__registerDict["serviceIp"] = serviceIp
self.__registerDict["servicePort"] = servicePort
self.__registerDict["serviceName"] = serviceName
self.__registerDict["namespaceId"] = namespaceId
self.__registerDict["groupName"] = groupName
self.__registerDict["clusterName"] = clusterName
self.__registerDict["ephemeral"] = ephemeral
self.__registerDict["metadata"] = metadata
self.__registerDict["weight"] = weight
self.__registerDict["enabled"] = enabled

self.__registerDict["healthy"] = int(time.time())


registerUrl = "http://" + self.ip + ":" + str(self.port) + "/nacos/v1/ns/instance"
params = {
"ip": serviceIp,
"port": servicePort,
"serviceName": serviceName,
"namespaceId": namespaceId,
"groupName": groupName,
"clusterName": clusterName,
"ephemeral": ephemeral,
"metadata": json.dumps(metadata),
"weight": weight,
"enabled": enabled
}
try:
re = requests.post(registerUrl, params=params)
if (re.text == "ok"):
logging.info("服务注册成功。")
beatThread = threading.Thread(target=self.__registerBeatThreadRun,
args=(serviceIp,servicePort,serviceName,
groupName,namespaceId,metadata,weight,clusterName))
beatThread.start()
else:
logging.error("服务注册失败 "+re.text)
except:
logging.exception("服务注册失败",exc_info=True)

def fallbackFun():
return "request Error"
def timeOutFun():
return "request time out"

class nacosBalanceClient:
def __init__(self,ip="127.0.0.1",port=8848,serviceName="",
group="DEFAULT_GROUP",namespaceId="public",timeout=6,
fallbackFun=fallbackFun, timeOutFun=timeOutFun):
self.ip = ip
self.port = port
self.serviceName = serviceName
self.group = group
self.namespaceId = namespaceId
self.__LoadBalanceDict = {}
self.timeout = timeout
self.fallbackFun = fallbackFun
self.timeOutFun = timeOutFun

def __doRequest(self,method,url,requestParamJson,*args,**kwargs) :
if method == "GET" or method == "get":
url = url + "/"
for item in args:
url = url + str(item) + "/"
url = url[:-1]
if kwargs.__len__() != 0:
url = url + "?"
for item in kwargs:
url = url + str(item) + "=" + str(kwargs[item]) + "&"
url = url[:-1]
return requests.get(url, timeout=self.timeout).text
if method == "POST" or method == "post":
if requestParamJson:
header = {"Content-type": "application/json;charset=utf-8"}
data = None
for item in args:
data = item
return requests.post(url,headers=header,data=json.dumps(data,ensure_ascii=False).encode("utf-8"), timeout=self.timeout).text
else:
files = {}
for map in args:
for key in map:
files[key] = (None,map[key])
return requests.post(url,files=files, timeout=self.timeout).text

def __getAddress(self,serviceName,group,namespaceId):
getProviderUrl = "http://" + self.ip + ":" + str(self.port) + "/nacos/v1/ns/instance/list"
params = {
"serviceName": serviceName,
"groupName": group,
"namespaceId": namespaceId
}
re = requests.get(getProviderUrl, params=params)
try:
msg = re.json()['hosts']
except json.JSONDecodeError:
msg = []
hosts = []
for item in msg:
hosts.append({
'ip': item['ip'],
'port': item['port'],
'healthy': item['healthy']
})
md5 = hashlib.md5()
md5.update(json.dumps(hosts,ensure_ascii=False).encode("utf-8"))
md5Content = md5.hexdigest()
try:
oldMd5 = self.__LoadBalanceDict[serviceName + group + namespaceId + "md5"]
except KeyError:
self.__LoadBalanceDict[serviceName + group + namespaceId + "md5"] = md5Content
oldMd5 = ""
if oldMd5 != md5Content:
healthyHosts = []
for host in msg:
if host['healthy'] == True:
healthyHosts.append(host)
self.__LoadBalanceDict[serviceName + group + namespaceId] = healthyHosts
self.__LoadBalanceDict[serviceName + group + namespaceId + "index"] = 0

def __loadBalanceClient(self,serviceName,group,namespaceId):
try:
x = int(time.time()) - self.__LoadBalanceDict[serviceName + group + namespaceId + "time"]
except KeyError:
x = 11
if x > 10:
self.__getAddress(serviceName,group,namespaceId)
self.__LoadBalanceDict[serviceName + group + namespaceId + "time"] = int(time.time())

index = self.__LoadBalanceDict[serviceName + group + namespaceId + "index"]
l = len(self.__LoadBalanceDict[serviceName + group + namespaceId])
if l == 0:
logging.error("无可用服务 serviceName: "+serviceName+";group: "+group+";namespaceId: "+namespaceId)
return ""
if index >= l:
self.__LoadBalanceDict[serviceName + group + namespaceId + "index"] = 1
return self.__LoadBalanceDict[serviceName + group + namespaceId][0]['ip']+":"+str(self.__LoadBalanceDict[serviceName + group + namespaceId][0]['port'])
else:
self.__LoadBalanceDict[serviceName + group + namespaceId + "index"] = index + 1
return self.__LoadBalanceDict[serviceName + group + namespaceId][index]['ip'] + ":" + str(self.__LoadBalanceDict[serviceName + group + namespaceId][index]['port'])

def customRequestClient(self,method,url,
requestParamJson=False,https=False):
def requestPro(f):
def mainPro(*args, **kwargs):
address = self.__loadBalanceClient(self.serviceName, self.group, self.namespaceId)
if address == "":
return
else:
if https:
requestUrl = "https://" + address + url
else:
requestUrl = "http://" + address + url
try:
return self.__doRequest(method, requestUrl, requestParamJson, *args, **kwargs)
except requests.ConnectTimeout:
logging.exception("链接超时 ",exc_info=True)
return self.timeOutFun(self.serviceName,self.group,self.namespaceId,method,url)
except Exception as ex:
logging.exception("链接失败 ", exc_info=True)
return self.fallbackFun(self.serviceName,self.group,self.namespaceId,method,url,ex)
mainPro.__name__ = f.__name__
return mainPro
return requestPro

此时package的功能就完成了,接下来就准备调整包的一些基本信息

调整package基本信息

调整setup.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
[root@jenkins-manager xadnacos]# ll
total 44
-rw-r--r-- 1 root root 151 Feb 4 14:29 AUTHORS.rst
-rw-r--r-- 1 root root 3536 Feb 4 14:29 CONTRIBUTING.rst
drwxr-xr-x 2 root root 191 Feb 4 14:29 docs
-rw-r--r-- 1 root root 89 Feb 4 14:29 HISTORY.rst
-rw-r--r-- 1 root root 1067 Feb 4 14:29 LICENSE
-rw-r--r-- 1 root root 2266 Feb 4 14:29 Makefile
-rw-r--r-- 1 root root 262 Feb 4 14:29 MANIFEST.in
-rw-r--r-- 1 root root 846 Feb 4 14:29 README.rst
-rw-r--r-- 1 root root 144 Feb 4 14:29 requirements_dev.txt
-rw-r--r-- 1 root root 392 Feb 4 14:29 setup.cfg
-rw-r--r-- 1 root root 1642 Feb 4 14:55 setup.py
drwxr-xr-x 2 root root 49 Feb 4 14:29 tests
-rw-r--r-- 1 root root 282 Feb 4 14:29 tox.ini
drwxr-xr-x 2 root root 58 Feb 4 15:11 xadnacos
[root@jenkins-manager xadnacos]# cat setup.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""The setup script."""

from setuptools import setup, find_packages

with open('README.rst', "r", encoding="utf-8") as readme_file:
readme = readme_file.read()

with open('HISTORY.rst', "r", encoding="utf-8") as history_file:
history = history_file.read()

requirements = ['Click>=7.0', 'requests>=2.20.0']

setup_requirements = [ ]

test_requirements = [ ]

setup(
author="KONE-XAD",
author_email='1793360097@qq.com',
python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*',
classifiers=[
'Development Status :: 2 - Pre-Alpha',
'Intended Audience :: Developers',
'License :: OSI Approved :: MIT License',
'Natural Language :: English',
"Programming Language :: Python :: 2",
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
],
description="python sdk for nacos",
entry_points={
'console_scripts': [
'xadnacos=xadnacos.cli:main',
],
},
install_requires=requirements,
license="MIT license",
long_description=readme + '\n\n' + history,
include_package_data=True,
keywords='xadnacos',
name='xadnacos',
packages=find_packages(include=['xadnacos', 'xadnacos.*']),
setup_requires=setup_requirements,
test_suite='tests',
tests_require=test_requirements,
url='https://github.com/KONE-XAD/xadnacos',
version='0.1.0',
zip_safe=False,
)

编写README配置

安装打包依赖

1
2
[root@jenkins-manager xadnacos]# pip3 install --upgrade pip
[root@jenkins-manager xadnacos]# pip3 install twine setuptools setuptools-rust cffi wheel -i https://mirrors.aliyun.com/pypi/simple/

开始打包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
[root@jenkins-manager xadnacos]# python3 setup.py sdist bdist_wheel
running sdist
running egg_info
creating xadnacos.egg-info
writing xadnacos.egg-info/PKG-INFO
writing dependency_links to xadnacos.egg-info/dependency_links.txt
writing entry points to xadnacos.egg-info/entry_points.txt
writing requirements to xadnacos.egg-info/requires.txt
writing top-level names to xadnacos.egg-info/top_level.txt
writing manifest file 'xadnacos.egg-info/SOURCES.txt'
reading manifest file 'xadnacos.egg-info/SOURCES.txt'
reading manifest template 'MANIFEST.in'
warning: no previously-included files matching '__pycache__' found under directory '*'
warning: no previously-included files matching '*.py[co]' found under directory '*'
warning: no files found matching '*.jpg' under directory 'docs'
warning: no files found matching '*.png' under directory 'docs'
warning: no files found matching '*.gif' under directory 'docs'
adding license file 'LICENSE'
adding license file 'AUTHORS.rst'
writing manifest file 'xadnacos.egg-info/SOURCES.txt'
running check
creating xadnacos-0.1.0
creating xadnacos-0.1.0/docs
creating xadnacos-0.1.0/tests
creating xadnacos-0.1.0/xadnacos
creating xadnacos-0.1.0/xadnacos.egg-info
copying files to xadnacos-0.1.0...
copying AUTHORS.rst -> xadnacos-0.1.0
copying CONTRIBUTING.rst -> xadnacos-0.1.0
copying HISTORY.rst -> xadnacos-0.1.0
copying LICENSE -> xadnacos-0.1.0
copying MANIFEST.in -> xadnacos-0.1.0
copying README.rst -> xadnacos-0.1.0
copying setup.cfg -> xadnacos-0.1.0
copying setup.py -> xadnacos-0.1.0
copying docs/Makefile -> xadnacos-0.1.0/docs
copying docs/authors.rst -> xadnacos-0.1.0/docs
copying docs/conf.py -> xadnacos-0.1.0/docs
copying docs/contributing.rst -> xadnacos-0.1.0/docs
copying docs/history.rst -> xadnacos-0.1.0/docs
copying docs/index.rst -> xadnacos-0.1.0/docs
copying docs/installation.rst -> xadnacos-0.1.0/docs
copying docs/make.bat -> xadnacos-0.1.0/docs
copying docs/readme.rst -> xadnacos-0.1.0/docs
copying docs/usage.rst -> xadnacos-0.1.0/docs
copying tests/__init__.py -> xadnacos-0.1.0/tests
copying tests/test_xadnacos.py -> xadnacos-0.1.0/tests
copying xadnacos/__init__.py -> xadnacos-0.1.0/xadnacos
copying xadnacos/cli.py -> xadnacos-0.1.0/xadnacos
copying xadnacos/xadnacos.py -> xadnacos-0.1.0/xadnacos
copying xadnacos.egg-info/PKG-INFO -> xadnacos-0.1.0/xadnacos.egg-info
copying xadnacos.egg-info/SOURCES.txt -> xadnacos-0.1.0/xadnacos.egg-info
copying xadnacos.egg-info/dependency_links.txt -> xadnacos-0.1.0/xadnacos.egg-info
copying xadnacos.egg-info/entry_points.txt -> xadnacos-0.1.0/xadnacos.egg-info
copying xadnacos.egg-info/not-zip-safe -> xadnacos-0.1.0/xadnacos.egg-info
copying xadnacos.egg-info/requires.txt -> xadnacos-0.1.0/xadnacos.egg-info
copying xadnacos.egg-info/top_level.txt -> xadnacos-0.1.0/xadnacos.egg-info
Writing xadnacos-0.1.0/setup.cfg
creating dist
Creating tar archive
removing 'xadnacos-0.1.0' (and everything under it)
running bdist_wheel
running build
running build_py
creating build
creating build/lib
creating build/lib/xadnacos
copying xadnacos/__init__.py -> build/lib/xadnacos
copying xadnacos/cli.py -> build/lib/xadnacos
copying xadnacos/xadnacos.py -> build/lib/xadnacos
/usr/local/lib/python3.6/site-packages/setuptools/command/install.py:37: SetuptoolsDeprecationWarning: setup.py install is deprecated. Use build and pip and other standards-based tools.
setuptools.SetuptoolsDeprecationWarning,
installing to build/bdist.linux-x86_64/wheel
running install
running install_lib
creating build/bdist.linux-x86_64
creating build/bdist.linux-x86_64/wheel
creating build/bdist.linux-x86_64/wheel/xadnacos
copying build/lib/xadnacos/__init__.py -> build/bdist.linux-x86_64/wheel/xadnacos
copying build/lib/xadnacos/cli.py -> build/bdist.linux-x86_64/wheel/xadnacos
copying build/lib/xadnacos/xadnacos.py -> build/bdist.linux-x86_64/wheel/xadnacos
running install_egg_info
Copying xadnacos.egg-info to build/bdist.linux-x86_64/wheel/xadnacos-0.1.0-py3.6.egg-info
running install_scripts
adding license file "LICENSE" (matched pattern "LICEN[CS]E*")
adding license file "AUTHORS.rst" (matched pattern "AUTHORS*")
creating build/bdist.linux-x86_64/wheel/xadnacos-0.1.0.dist-info/WHEEL
creating 'dist/xadnacos-0.1.0-py2.py3-none-any.whl' and adding 'build/bdist.linux-x86_64/wheel' to it
adding 'xadnacos/__init__.py'
adding 'xadnacos/cli.py'
adding 'xadnacos/xadnacos.py'
adding 'xadnacos-0.1.0.dist-info/AUTHORS.rst'
adding 'xadnacos-0.1.0.dist-info/LICENSE'
adding 'xadnacos-0.1.0.dist-info/METADATA'
adding 'xadnacos-0.1.0.dist-info/WHEEL'
adding 'xadnacos-0.1.0.dist-info/entry_points.txt'
adding 'xadnacos-0.1.0.dist-info/top_level.txt'
adding 'xadnacos-0.1.0.dist-info/RECORD'
removing build/bdist.linux-x86_64/wheel

# 执行完后,将在新创建的dist目录中创建两个文件,一个源归档文件和一个wheel文件
[root@jenkins-manager xadnacos]# ll
total 44
-rw-r--r-- 1 root root 151 Feb 4 14:29 AUTHORS.rst
drwxr-xr-x 4 root root 43 Feb 4 15:17 build
-rw-r--r-- 1 root root 3536 Feb 4 14:29 CONTRIBUTING.rst
drwxr-xr-x 2 root root 78 Feb 4 15:17 dist
drwxr-xr-x 2 root root 191 Feb 4 14:29 docs
-rw-r--r-- 1 root root 89 Feb 4 14:29 HISTORY.rst
-rw-r--r-- 1 root root 1067 Feb 4 14:29 LICENSE
-rw-r--r-- 1 root root 2266 Feb 4 14:29 Makefile
-rw-r--r-- 1 root root 262 Feb 4 14:29 MANIFEST.in
-rw-r--r-- 1 root root 846 Feb 4 14:29 README.rst
-rw-r--r-- 1 root root 144 Feb 4 14:29 requirements_dev.txt
-rw-r--r-- 1 root root 392 Feb 4 14:29 setup.cfg
-rw-r--r-- 1 root root 1642 Feb 4 15:16 setup.py
drwxr-xr-x 2 root root 49 Feb 4 14:29 tests
-rw-r--r-- 1 root root 282 Feb 4 14:29 tox.ini
drwxr-xr-x 2 root root 58 Feb 4 15:11 xadnacos
drwxr-xr-x 2 root root 154 Feb 4 15:17 xadnacos.egg-info
[root@jenkins-manager xadnacos]# ll dist/
total 20
-rw-r--r-- 1 root root 7139 Feb 4 15:17 xadnacos-0.1.0-py2.py3-none-any.whl
-rw-r--r-- 1 root root 11691 Feb 4 15:17 xadnacos-0.1.0.tar.gz

发布package到pypi仓库

配置pypi仓库即账号密码

1
2
3
4
5
6
7
8
[root@jenkins-manager xadnacos]# cat ~/.pypirc
[distutils]
index-servers=pypi

[pypi]
repository = https://upload.pypi.org/legacy/
username = <username>
password = <password>

开始上传

1
2
3
4
5
6
7
8
9
10
11
[root@jenkins-manager xadnacos]# twine upload dist/xadnacos-0.1.0*
/usr/local/lib/python3.6/site-packages/requests/__init__.py:104: RequestsDependencyWarning: urllib3 (1.26.12) or chardet (5.0.0)/charset_normalizer (2.0.12) doesn't match a supported version!
RequestsDependencyWarning)
Uploading distributions to https://upload.pypi.org/legacy/
Uploading xadnacos-0.1.0-py2.py3-none-any.whl
100%████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ 12.1k/12.1k [00:03<00:00, 3.79kB/s]
Uploading xadnacos-0.1.0.tar.gz
100%████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ 16.3k/16.3k [00:02<00:00, 7.85kB/s]

View at:
https://pypi.org/project/xadnacos/0.1.0/

此时打开提示的连接:https://pypi.org/project/xadnacos/0.1.0/

发布下一个版本

修改完功能后编辑setup.py文件,将里面的version跟换即可,此处修改REAME.txt做示范

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
[root@jenkins-manager xadnacos]# cat README.rst
========
xadnacos
========


.. image:: https://img.shields.io/pypi/v/xadnacos.svg
:target: https://pypi.python.org/pypi/xadnacos

.. image:: https://img.shields.io/travis/KONE-XAD/xadnacos.svg
:target: https://travis-ci.org/KONE-XAD/xadnacos

.. image:: https://readthedocs.org/projects/xadnacos/badge/?version=latest
:target: https://xadnacos.readthedocs.io/en/latest/?badge=latest
:alt: Documentation Status




python sdk for nacos


* Free software: MIT license
* Documentation: https://xadnacos.readthedocs.io.


Features
--------

* TODO

Credits
-------

This package was created with Cookiecutter_ and the `audreyr/cookiecutter-pypackage`_ project template.

.. _Cookiecutter: https://github.com/audreyr/cookiecutter
.. _`audreyr/cookiecutter-pypackage`: https://github.com/audreyr/cookiecutter-pypackage

修改setup.py中的版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
[root@jenkins-manager xadnacos]# cat setup.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""The setup script."""

from setuptools import setup, find_packages

with open('README.rst', 'r', encoding='utf-8') as readme_file:
readme = readme_file.read()

with open('HISTORY.rst', 'r', encoding='utf-8') as history_file:
history = history_file.read()

requirements = ['Click>=7.0', 'requests>=2.20.0']

setup_requirements = [ ]

test_requirements = [ ]

setup(
author="KONE-XAD",
author_email='1793360097@qq.com',
python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*',
classifiers=[
'Development Status :: 2 - Pre-Alpha',
'Intended Audience :: Developers',
'License :: OSI Approved :: MIT License',
'Natural Language :: English',
"Programming Language :: Python :: 2",
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
],
description="python sdk for nacos",
entry_points={
'console_scripts': [
'xadnacos=xadnacos.cli:main',
],
},
install_requires=requirements,
license="MIT license",
long_description=readme + '\n\n' + history,
include_package_data=True,
keywords='xadnacos',
name='xadnacos',
packages=find_packages(include=['xadnacos', 'xadnacos.*']),
setup_requires=setup_requirements,
test_suite='tests',
tests_require=test_requirements,
url='https://github.com/KONE-XAD/xadnacos',
version='0.1.3',
zip_safe=False,
)

重新生成包并上传

1
2
3
4
5
6
7
8
9
10
11
12
[root@jenkins-manager xadnacos]# python3 setup.py sdist bdist_wheel
[root@jenkins-manager xadnacos]# twine upload dist/xadnacos-0.1.3*
/usr/local/lib/python3.6/site-packages/requests/__init__.py:104: RequestsDependencyWarning: urllib3 (1.26.12) or chardet (5.0.0)/charset_normalizer (2.0.12) doesn't match a supported version!
RequestsDependencyWarning)
Uploading distributions to https://upload.pypi.org/legacy/
Uploading xadnacos-0.1.3-py2.py3-none-any.whl
100%████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ 13.6k/13.6k [00:03<00:00, 4.49kB/s]
Uploading xadnacos-0.1.3.tar.gz
100%████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ 17.7k/17.7k [00:02<00:00, 8.08kB/s]

View at:
https://pypi.org/project/xadnacos/0.1.3/