You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by qi...@apache.org on 2019/09/27 11:06:09 UTC
[incubator-iotdb] branch master updated: [IOTDB-221]Add a python
client example (#427)
This is an automated email from the ASF dual-hosted git repository.
qiaojialin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-iotdb.git
The following commit(s) were added to refs/heads/master by this push:
new 6908460 [IOTDB-221]Add a python client example (#427)
6908460 is described below
commit 6908460f607a2b4c60c3f53ae555cd4907659b67
Author: Jiang Tian <jt...@163.com>
AuthorDate: Fri Sep 27 19:06:04 2019 +0800
[IOTDB-221]Add a python client example (#427)
* add client-py
---
.gitignore | 3 +-
client-py/compile.bat | 28 ++++++++
client-py/compile.sh | 28 ++++++++
client-py/readme.md | 42 +++++++++++
client-py/src/client_example.py | 151 ++++++++++++++++++++++++++++++++++++++++
5 files changed, 251 insertions(+), 1 deletion(-)
diff --git a/.gitignore b/.gitignore
index 6691ce4..18a7508 100644
--- a/.gitignore
+++ b/.gitignore
@@ -85,4 +85,5 @@ grafana/data/test.csv
tsfile/src/test/resources/*.ts
### Apache release ###
-local-snapshots-dir/
\ No newline at end of file
+local-snapshots-dir/
+venv/
diff --git a/client-py/compile.bat b/client-py/compile.bat
new file mode 100644
index 0000000..a9081c0
--- /dev/null
+++ b/client-py/compile.bat
@@ -0,0 +1,28 @@
+@REM
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM
+
+@echo off
+set THRIFT_EXE=C:\bin\thrift-0.12.0.exe
+set BAT_DIR=%~dp0
+set THRIFT_SCRIPT=%BAT_DIR%..\service-rpc\src\main\thrift\rpc.thrift
+set THRIFT_OUT=%BAT_DIR%target
+
+rm -rf %THRIFT_OUT%
+mkdir %THRIFT_OUT%
+%THRIFT_EXE% -gen py -out %THRIFT_OUT% %THRIFT_SCRIPT%
diff --git a/client-py/compile.sh b/client-py/compile.sh
new file mode 100644
index 0000000..628ca82
--- /dev/null
+++ b/client-py/compile.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless 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.
+#
+
+export THRIFT_EXE=thrift
+export SH_DIR=$(dirname $0)/
+export THRIFT_SCRIPT=${SH_DIR}../service-rpc/src/main/thrift/rpc.thrift
+export THRIFT_OUT=${SH_DIR}target
+
+rm -rf ${THRIFT_OUT}
+mkdir ${THRIFT_OUT}
+${THRIFT_EXE} -gen py -out ${THRIFT_OUT} ${THRIFT_SCRIPT}
diff --git a/client-py/readme.md b/client-py/readme.md
new file mode 100644
index 0000000..8b79c94
--- /dev/null
+++ b/client-py/readme.md
@@ -0,0 +1,42 @@
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless 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.
+
+-->
+
+# introduction
+This is an example of how to connect to IoTDB with python, using the thrift rpc interfaces. Things will be a bit different
+on Linux or Windows, we will introduce how to operate on the two systems separately.
+
+## Prerequisites
+python3.7 or later is preferred.
+
+You have to install Thrift (0.11.0 or later) to compile our thrift file into python code. Below is the official
+tutorial of installation:
+```
+http://thrift.apache.org/docs/install/
+```
+
+## Compile
+If you have added Thrift executable into your path, you may just run `compile.sh` or `compile.bat`, or you will have to
+modify it to set variable `THRIFT_EXE` to point to your executable. This will generate thrift sources under folder `target`,
+you can add it to your `PYTHONPATH` so that you would be able to use the library in your code.
+
+## Example
+We provided an example of how to use the thrift library to connect to IoTDB in `src\client_example.py`, please read it
+carefully before you write your own code.
diff --git a/client-py/src/client_example.py b/client-py/src/client_example.py
new file mode 100644
index 0000000..05faf83
--- /dev/null
+++ b/client-py/src/client_example.py
@@ -0,0 +1,151 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless 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.
+#
+
+import sys, struct
+sys.path.append("../target")
+
+from thrift.protocol import TBinaryProtocol
+from thrift.transport import TSocket, TTransport
+
+from rpc.TSIService import Client, TSCreateTimeseriesReq, TSInsertionReq, TSBatchInsertionReq, TSExecuteStatementReq,\
+ TS_SessionHandle, TSHandleIdentifier, TSOpenSessionReq, TSQueryDataSet, TSFetchResultsReq, TSCloseOperationReq,\
+ TSCloseSessionReq
+
+TSDataType = {
+ 'BOOLEAN' : 0,
+ 'INT32' : 1,
+ 'INT64' : 2,
+ 'FLOAT' : 3,
+ 'DOUBLE' : 4,
+ 'TEXT' : 5
+}
+
+TSEncoding = {
+ 'PLAIN' : 0,
+ 'PLAIN_DICTIONARY' : 1,
+ 'RLE' : 2,
+ 'DIFF' : 3,
+ 'TS_2DIFF' : 4,
+ 'BITMAP' : 5,
+ 'GORILLA' : 6,
+ 'REGULAR' : 7
+}
+
+Compressor = {
+ 'UNCOMPRESSED' : 0,
+ 'SNAPPY' : 1,
+ 'GZIP' : 2,
+ 'LZO' : 3,
+ 'SDT' : 4,
+ 'PAA' : 5,
+ 'PLA' : 6
+}
+
+
+if __name__ == '__main__':
+ ip = "localhost"
+ port = "6667"
+ username = 'root'
+ password = 'root'
+ # Make socket
+ transport = TSocket.TSocket(ip, port)
+
+ # Buffering is critical. Raw sockets are very slow
+ transport = TTransport.TBufferedTransport(transport)
+
+ # Wrap in a protocol
+ protocol = TBinaryProtocol.TBinaryProtocol(transport)
+
+ # Create a client to use the protocol encoder
+ client = Client(protocol)
+
+ # Connect!
+ transport.open()
+
+ # Authentication
+ client.openSession(TSOpenSessionReq(username=username, password=password))
+
+ # This is necessary for resource control
+ stmtId = client.requestStatementId()
+
+ # These two fields do not matter
+ handle = TS_SessionHandle(TSHandleIdentifier(b'uuid', b'secret'))
+
+ # create a storage group
+ status = client.setStorageGroup("root.group1")
+ print(status.statusType)
+
+ # create timeseries
+ status = client.createTimeseries(TSCreateTimeseriesReq("root.group1.s1", TSDataType['INT64'], TSEncoding['PLAIN'],
+ Compressor['UNCOMPRESSED']))
+ print(status.statusType)
+ status = client.createTimeseries(TSCreateTimeseriesReq("root.group1.s2", TSDataType['INT64'], TSEncoding['PLAIN'],
+ Compressor['UNCOMPRESSED']))
+ print(status.statusType)
+ status = client.createTimeseries(TSCreateTimeseriesReq("root.group1.s3", TSDataType['INT64'], TSEncoding['PLAIN'],
+ Compressor['UNCOMPRESSED']))
+ print(status.statusType)
+
+ # insert a single row
+ status = client.insertRow(TSInsertionReq("root.group1", ["s1", "s2", "s3"], ["1", "11", "111"], 1, 1))
+ print(status.statusType)
+
+ # insert multiple rows, this interface is more efficient
+ values = bytearray()
+ times = bytearray()
+ deviceId = "root.group1"
+ measurements = ["s1", "s2", "s3"]
+ dataSize = 3
+ dataTypes = [TSDataType['INT64'], TSDataType['INT64'], TSDataType['INT64']]
+ # the first 3 belong to 's1', the mid 3 belong to 's2', the last 3 belong to 's3'
+ values.extend(struct.pack('>qqqqqqqqq', 2, 3, 4, 22, 33, 44, 222, 333, 444))
+ times.extend(struct.pack('>qqq', 2, 3, 4))
+ resp = client.insertBatch(TSBatchInsertionReq(deviceId, measurements, values, times,
+ dataTypes, dataSize))
+ status = resp.status
+ print(status.statusType)
+
+ # execute deletion (or other statements)
+ resp = client.executeStatement(TSExecuteStatementReq(handle, "DELETE FROM root.group1 where time < 2"))
+ status = resp.status
+ print(status.statusType)
+
+ # query the data
+ stmt = "SELECT * FROM root.group1"
+ fetchSize = 2
+ # this is also for resource control, make sure different queries will not use the same id at the same time
+ queryId = 1
+ resp = client.executeQueryStatement(TSExecuteStatementReq(handle, stmt))
+ stmtHandle = resp.operationHandle
+ status = resp.status
+ print(status.statusType)
+ while True:
+ rst = client.fetchResults(TSFetchResultsReq(stmt, fetchSize, queryId)).queryDataSet
+ records = rst.records
+ if len(records) == 0:
+ break
+ for record in records:
+ print(record)
+
+ # do not forget to close it when a query is over
+ client.closeOperation(TSCloseOperationReq(stmtHandle, queryId, stmtId))
+
+ # and do not forget to close the session before exiting
+ client.closeSession(TSCloseSessionReq(handle))
+
+