반응형


+ 자료 처리 및 많이 사용하는 함수들...

-Shape, Rank, Axis
t=tf.constant(  [1,2,3,4])
tf.shape(t).eval()
     tensor의 shape과 타입을 알수 있다.   Rank는 처음에 [의 개수로 볼 수 있음.
     array ( [4],  dtype=int32 )

t=tf.constant(  [[1,2],  [3,4] ])
tf.shape(t).eval()
     array ( [2,2],  dtype=int32 )

     축에도 번호를 매길수 있는데, 가장큰 범위부터 0으로 매김.
     2차원배열의 경우 0은 행방향, 1은 열 방향.

-Matrix 곱

tf.matmul( matrix1, matrix2)          ; Matrix 곱; 내적
matrix1*matrix2     ; 성분곱.
 ( *과 matmul은 다름. 주의!)

;Broadcasting  알아서 형을 변환하여 연산해 줌. (편하지만 주의할 필요가 있음)



-reduce_sum( input_tensor, axis=None)

axis가 없으면 총합. 축은 큰 범위에서부터 인덱스가 0임.

입력이 1차원이면 축은 의미없음. axis=0이 됨.
입력이 2차원이면
axis=0 세로방향으로 합.  (테이블 input이 있으면, 아래에 답을 쓴 것)
axis=1 가로방향으로 합. (테이블 input에서 오른쪽에 답을 단 것)
axis=-1 이면 가장 마지막 축. 2차원에서는 1이됨. 3차원에서는 2가 됨.
axis가 없으면 성분들 총합.


-reduce_mean( tensor, axis )
평균
tf.reduce_mean(x, axis=0)

-argmax  ; 최대값의 인덱스
tf.argmax(x, axis=1)

-reshape ; 텐서 재구성
t=np.array( [[[0,1,2], [3,4,5]],    [[6,7,8],[9,10,11]] ] )
tf.reshape(t, shape=[-1,3])  ; -1은 알아서 다른 성분크기에 맞게 자동조정.
[[0,1,2], [3,4,5], [6,7,8], [9,10,11]]

비슷한 함수. squeeze, expand

-onehot encoding
t=tf.one_hot(  [[0], [1], [2], [0]],  depth=3)
[ [[1, 0, 0]] , [[0,1,0]], [[0,0,1]], [[1,0,0]] ]          #주의 rank가 올라감!!!
원래의 차수로 내리려면
tf.reshape ( t, [-1, 3] )
[ [1,0,0], [0,1,0], [0,0,1], [1,0,0] ]


-타입 캐스팅
tf.cast( [1.8, 2.2], tf.int32)
tf.cast(  [True, False, 1==1, 1==0], tf.int32 )
     [1, 0, 1, 0]

-스택
x=[1,2], y=[3,4], z=[5,6]
np.stack( [x,y,z] )
          =>   [[1,2], [3,4], [5,6]]
np.stack( [x,y,z], axis=1)
          =>  [[1, 3, 5], [2,4,6]]

-ones and zeros like
tf.ones_like(x).eval()          # .eval()은 값과 타입을 출력해준다.
x의 shape과 같은데 값을 모두 1로 채움.
tf.zeros_like(x)

-Zip ; 묶어준다.
for x, y, z in zip( [1,2,3], [4,5,6], [7,8,9] ):
     print (x, y, z)   
1 4 7 
2 5 8
3 6 9
zip을 하지 않고 출력하면?
for x, y, z in ( [1,2,3], [4,5,6], [7,8,9] ):          # 또는 [[1,2,3],[4,5,6],[7,8,9]]
     print (x, y, z)   
1 2 3
4 5 6
7 8 9



반응형



+자료형

1. PlaceHolder
텐서를 저장. (핸들값). 바로 계산되지는 않는다.
input data 저장시. feed dictionary=맵핑시켜주는 역할. (입력값들로 그래프 실행시 입력할 수 있다.)

tf.placeholder(dtype, shape=None, name=None)
     데이터 타입(dtype);     tf.float32, tf....

     p1 = tf.placeholder(tf.float32, shape=(3,3))
     feeding을 해주어야 한다.

# place holder test
ph1 = tf.placeholder(tf.float32)
ph2 = tf.placeholder(tf.float32)
ph3 = tf.placeholder(tf.float32)

value1=3
value2=4
value3=5

feed_dict = {ph1:value1, ph2:value2, ph3:value3}

ph4 = ph1+ph2*ph3

result=s1.run(ph4, feed_dict)
#or  result = s1.run(ph4, {ph1:value1, ph2:value2, ph3:[2.3]})
print(result)



2. Variable (대문자V 주의!)
     weight를 저장시 사용. (그래프 계산시에 내부에서 변경되는 값들. 초기화가 필요.)
v1 = tf.Variable([1,2,3,4], dtype=tf.float32)
v2 = tf.Variable([1,2,3,4], dtype=tf.float32)
v3=v1*v2
print(v3) ; 역시 출력되지 않는다.
sess.run(v3) ; 에러 발생!
원인은 variable은 반드시 초기화가 필요하다. (weight 초기화 같이)
sess.run 전에 반드시 초기화를 돌려주어야한다. (예외, 저장된 vars restore의 경우는 안해도 됨.)
init = tf.global_variables_initializer()
sess.run(init)
또는
     sess.run( tf.global_variables_initializer())

이후부터 sess.run(v3)하면 계산이 된다.

초기화시킨 variables

weights = tf.Variable( tf.random_normal([784,200], stddev=0.35), name="weights")
또는
weights = tf.Variable( tf.truncated_normal( [None, 200] ) )

biases = tf.Variable(tf.zeros([200]), name="biases")

-변수의 값 변경assign()으로 한다.
gradient = tf.reduce_mean( (W*X-Y)*X)
descent = W-0.1*gradient
update = W.assign(descent)
sess.run(update)



3. constant
tf.zeros(shape, dtype=tf.float32, name=None)
tf.zeros_like(tensor, dtype=None, name=None, optimizer=True)
tf.ones(...)
tf.constant(value, dtype=None, shape=None, ..)

c1 = tf.zeros([3,4], tf.int32)


위 값들을 직접 print하면 객체 정보만 나오고 실제 값을 알 수 없음.
세션을 만들고 실행해 줘야 함.


4. Session   세션.
연산 그래프 묶음을 의미.
세션.run() . 세션단위로 실행. (그래프 실행)

import tensorflow as tf
hello = tf.constant('Hello, TensorFlow!')
sess = tf.Session()
print( sess.run(hello))

세션에 입력되는 텐서는 그래프 말단 노드로 보면 된다. 앞에 있는 것을 따라서 다 실행됨.
run시에 텐서 맵핑 테이블 추가하여  placeholder와 값을 맵핑시킨다.
run의 결과로 받으면 데이터를 로딩 및 출력이 가능하다. Weight, bias 정보를 얻을 수 있다.

result = sess.run(hello)
w = sess.run(w)
b = sess.run(b)
print(result)


tensor_map={x:input_x, y_:output_y}
_,tmp_cost,acc = sess.run( [train, cost, accuracy], tensor_map)
출력이 필요없는 것은 _로 받으면 된다.


다른 출력 방법??? eval() 이용
print ("Accuracy:", accuracy.eval( session=sess, feed_dict={x:inputx, y:outputy}) )

단,  sess = InteractiveSession() 으로 디폴트 세션을 열어주어야 한다.


마지막에 세션 close를 위해서 with as 구문 사용
with tf.Session() as sess:
     sess.run(train)
자동으로 위 블록탈출시 sess.close() 됨.




반응형



+TensorFlow

machine learning 오픈소스 라이브러리. python 기반.
계산 그래프(computational graph) 를 생성하여 텐서가 흐르는 프로그램


+ 로딩
import tensorflow as tf

로딩이 안되면 tensorflow를 설치한다.



+버전 확인
tf.__version__
'1.1.0'


+텐서 (Tensor)
Rank ; 차원
여기서는 모든 자료형이 텐서다. 원래는 정적타입의 n차원 배열 or list ; 랭크값이 차원수. 1차원은 벡터, 2차원은 매트릭스, 3차원부터 텐서다.
rank 0 ; scalar 1
rank 1 ; vector [1,2,3]
rank 2 ; matrix [[1,2],[3,4]]
rank 3 ; 3-tensor [ [[1],[2]], [[3],[4]] ]
rank n ; n-tensor

Shape ; dimension number. 
rank 1 ;  shape [4]
rank 2 ;  shape [4,2]  ; 4x2 행렬
rank 3 ;  shape [3,4,5]    ; 3x4x5 행렬

DataTypes
tf.float32     ; 대부분 함수에서 디폴트 자료형임.
tf.float64
tf.int8, 16, 32, 64
tf.uint8, 16
tf.string
tf.bool
tf.complex64, 128



+ 기본 예제, 작동 확인:   hello world -> hello tensorflow

import tensorflow as tf
hello = tf.constant('Hello tensorflow!')
sess = tf.Session()
print ( sess.run(hello) )
-------------
b'Hello tensorflow!'
위와 같이 출력됨.
b는 bytes를 의미. 


------------------------------------------------------------------
+ 간단한 더하기 계산그래프 테스트

3+4를 계산하는 그래프.

import tensorflow as tf
# build graph(tensor)
node1=tf.constant(3.0, tf.float32)
node2=tf.constant(4.0)
node3 = tf.add(node1, node2)
# 위 값을 print("node1=",node1, "node2=",node2, "node3=",node3)로 출력해 봐야 주소와 타입만 찍힌다. 값을 모름.
# feed data and run graph, update vars and return.
sess = tf.Session()
print ( sess.run( [node1, node2] ) )          # node1, node2를 구하여 출력.
print ( sess.run( [node3] ) )     # node3인 계산 결과를 출력. (윗줄은 데이터 값을 확인하기 위한 디버깅용)
sess.close()



반응형


+LIBCURL 라이브러리로 POST data 전송하기 또는 curl 커맨드로 전송하기

https도 가능함.


#include <curl/curl.h>

#include <syslog.h>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <ctype.h>


#define CURLCMD "curl"


struct PostResult {

size_t size;

char* ptr;

};



void init_string(struct PostResult *s)

{

s->size = 0;

s->ptr = malloc(s->size + 1);

if(s->ptr == NULL) {

fprintf(stderr," malloc() fail\n");

exit(EXIT_FAILURE);

}

s->ptr[0] = 0;

}


#ifdef _CURL_LIB_

static size_t

WriteCallback(void* ptr, size_t size, size_t nmemb, struct PostResult *s)

{

size_t new_len = s->size + size * nmemb;

s->ptr = realloc(s->ptr, new_len + 1);

if(s->ptr == NULL) {

fprintf(stderr, "ralloc fail\n");

exit(EXIT_FAILURE);

}

memcpy(s->ptr + s->size, ptr, size*nmemb);

s->ptr[new_len] = 0;

s->size = new_len;

return size*nmemb;

}

#endif


int Post_Send(char* url, char* jsonMsg)

{

#ifdef _CURL_LIB_

int i=0;

CURL *curl=NULL;

CURLcode res;

#endif

char inmsg[1024]={0,};

struct PostResult repost;

int maxsize=0 ;


// cmdline method

#ifdef _CURL_CMD_

char inmsg2[1024]={0,};

char cmdline[4096]={0,};

char result[1024]={0,};

#endif


if(!url || !jsonMsg) {

return -1;

}


init_string(&repost);


memset(inmsg, 0, sizeof(inmsg));

maxsize = strlen(jsonMsg)>sizeof(inmsg) ? sizeof(inmsg) : strlen(jsonMsg) ;

memcpy(inmsg, jsonMsg, maxsize) ;


// CURL 라이브러리 방식

#ifdef _CURL_LIB_

curl = curl_easy_init();

if(curl)

{

const int timeout = 30000;

i = strlen(inmsg);

curl_easy_setopt(curl, CURLOPT_URL, url);

curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);

curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);

curl_easy_setopt(curl, CURLOPT_POSTFIELDS, inmsg);

curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, strlen(inmsg));

curl_easy_setopt(curl, CURLOPT_POST, 1L);

curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout/1000);

curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);

curl_easy_setopt(curl, CURLOPT_WRITEDATA, &repost);


res = curl_easy_perform(curl);

if(CURLE_OK != res)

{

// server error

return 1;

}


if(repost.size > 1){

// 수신 데이터 주소 : repost.ptr

curl_easy_cleanup(curl);

return -1;

}else{

printf("error: %s\n", strerror(res));

curl_easy_cleanup(curl);

// server error

            return 1;

}

curl_easy_cleanup(curl);

}

#endif


// CURL 커맨드 방식

#ifdef _CURL_CMD_

{

int contimeout=10 ;  // secs

FILE *fp=NULL ;

int index=0 ;

int rbytes=0 ;


memset(inmsg2, 0, sizeof(inmsg2)) ;

q2dq(inmsg, inmsg2, sizeof(inmsg2)) ;    // " -> \"로 변경하는 함수

snprintf(cmdline, sizeof(cmdline)-1, "%s --connect-timeout %d -s -d \"%s\" -k \"%s\"",

  CURLCMD, contimeout, inmsg2, url) ;


fp = popen(cmdline, "r") ;

if ( fp==NULL ) {

// server error

}

else {

do {

rbytes=fread(result+index, 1, sizeof(result)-index-1, fp) ;

#ifdef _DEBUG

printf("rbytees=%d\n", rbytes) ;

#endif

if ( rbytes<=0 )

break; 

index+=rbytes ;

} while(rbytes!=0 );

pclose(fp) ;


#ifdef _DEBUG

printf("rcved=%s\n", result) ;

#endif

if( strlen(result)>1 ){

// 수신 데이터 주소: result

} else {

strcpy(tqResult->result, "100") ; // server error

}

#ifdef _DEBUG

printf("success post request\n");

#endif

}

}

#endif


return 0;

}



일부 함수는 없지만 적절히 수정하면 사용할 수 있다.


예를 들어 보내는 데이터를 "submit=1" 이렇게 하면 POST 수신쪽에서는 php의 경우 $_POST["submit"] 으로 받을 수 있다. 

form data가 아닌 raw data를 그대로 받으려면 

$post_raw_data = file_get_contents("php://input") ;

이렇게 한다.


다른 예제)

https://curl.haxx.se/libcurl/c/post-callback.html




반응형

+if or 비교시 어떤 식의 성공으로 진입했는지 구분

가끔 복수의 or 조건으로 진입한 경우, 어떤 식의 성공으로 왔는지 간단하게 구분이 필요할 수 있다.

다시 어떤 식인지 판단해줘야 하는데 귀찮은 작업이다.

어떤 식의 만족으로 먼저 들어왔는지 간단히 판단하려면... 다음과 같은 팁이 있다.


예를 들어, 입력값 조건 순서가 

1. 길이가 3이상이거나 

2. a로 시작하거나 

3. z로 끝난다.

위 세 조건을 or로 하여 먼저 만족하는 것은 어떤 것인가를 판단.


string str="....." ;

int ret=0 ;

if (  (ret=1, str.length()>=3 ) ||

    (ret=2, str.at(0)=='a') ||

   (ret=3, str.at( str.length()-1)=='z') ) {

std::cout << " match.  ret=" << ret << std::endl ;

 } else std::cout << " no match. " << std::endl ;


결과는 다음과 같다.

str="12345"  인 경우  ret=1  (길이 조건)

str="ab" 인 경우 ret=2 (a로 시작)

str="kz" 인 경우 ret=3 (z로 끝)

str="abz" 인 경우 ret=1 (길이 조건, a로 시작, z로 끝.  앞의 조건부터 판단하므로 ret=1로 됨.)







'Develop > C&CPP' 카테고리의 다른 글

const pointer or pointer / int *const / int const * / const int *  (0) 2018.07.19
libcurl HTTP POST send 모듈/curl 커맨드 방식도 지원  (0) 2018.07.13
Numerics library  (0) 2018.06.21
Preprocessor  (0) 2018.06.20
deque  (0) 2018.06.13
반응형


+mysql에서 쿼리 결과를 변수로 저장하여 사용하기


변수는 앞에 @을 붙인다.
변수에 값을 할당시 set, select로 할 수 있다. 할당시에는 := 로 한다. 

SET @user:=123456;
select @group:=group from TUSER where user=@user;
select * from user where group=@group;



반응형


+ SELECT AND INSERT
한 테이블에서 선택한 레코드들을 다른 테이블에 추가하기.  (values 대신 select 절을 사용)

INSERT INTO TABLEA (f1, f2, f3)
  SELECT f1, f2, f3 FROM TABLEB

데이터베이스가 다르면 테이블명 앞에 DB명을 써준다.
 ex)  DB1.TABLEA


+ SELECT AND UPDATE
다른 테이블에서  이 테이블의 특정필드로 select한 값을 이 테이블에서 다른 테이블의 값으로 업데이트를 한 번에 하기.

UPDATE TABLEA log, TABLEB user
SET log.MOBILE_NO = user.MOBILE_NO
WHERE log.DEVICE_ID=user.DEVICE_ID;





반응형

mysql

+그룹별로 처음 나오는 하나의 줄만 뽑아낼때


ex) CAT_ID가 같은 것들끼리 묶어서 그룹별 처음으로 나온 레코드만 그룹 대표로 하나씩 추출한다.

select * from TABLE_A group by CAT_ID ;


그룹 내에서 어떤 키로 소팅하여 최신 값을 뽑는 경우, min, max 함수등을 이용하거나 미리 order by로 정렬 후 group by로 한다.

ex)

select * from (select * from TABLE_A order by NAME desc) a group by a.CAT_ID ;

select CAT_ID, min(NAME) from TABLE_A group by CAT_ID ;



+ group by 에러

only_full_group_by 에러가 발생.

=> mysql 5.7이상 부터 group by로 select 할 때 다른 값들이 있는 컬럼들을 조회하면 에러 발생.

처음 나온 것들을 자동으로 선택하여 조회하게 하려면 서버 설정을 바꿔주어야 한다.

/etc/mysql/my.cnf

[mysqld]

sql_mode=STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION

위와 같이 설정을 추가하여 서비스 재시작

service mysql restart





반응형

python file i/o, directory, read/write

-파일 IO

파일객체=open(file, mode)

간략하게
f = open('a.txt') 이렇게도 된다.

-mode 
r ; read (default)
r+ ; read/write
w ; write
a    ; append
t    ; text mode (default)
b ; binary

contents=f.read()    ; 전체 읽기
str=f.readline()    ; 한 줄 읽기 (\n포함!), 더 읽을게 없으면 None 리턴.
strarray=f.readlines() ; 여러줄을 읽어 list로 반환. (\n포함!)

f = open('filename', 'mode')
while 1:
     line = f.readline()    # 마지막에 \n도 포함되어 줄 단위로 읽는다.
     if not line : break
     print(line)
f.write(buf)
f.close()

여러줄 읽기
lines = f.readlines()
tell(), seek() 지원



+ 파일 열기
f = open('c:\\users\\user01\\desktop\\a.txt', 'rt')
     오픈 모드 ; r=read, w=write
               t=text, b=binary
+ 읽기
lines = f.readlines()          # 여러줄 읽기. string list로 반환. (마지막에 \n도 포함됨.)                                     제거하려면, rstrip() 사용
f.close()

for line in lines:
     print(line, end="")     # 라인마지막에 \n이 포함되어 있어서 print에서 자체 \n을 제거하여 출력.


-파일 IO

파일객체=open(file, mode)
간략하게
f = open('a.txt') 이렇게도 된다.

-mode ; 
r ; read (default)
r+ ; read/write
w ; write
a    ; append
t    ; text mode (default)
b ; binary

f.read()    ; 전체 읽기
f.readline()    ; 한 줄 읽기 (\n포함), 더 읽을게 없으면 None 리턴.
f.readlines() ; 여러줄을 읽어 list로 반환. (\n포함)

f = open('filename', 'mode')
while 1:
     line = f.readline()    # 마지막에 \n도 포함되어 줄 단위로 읽는다.
     if not line : break
     print(line)
f.write(buf)
f.close()
모드는 r,w,a
여러줄 읽기
lines = f.readlines()
tell(), seek() 지원



+ 파일 열기
f = open('c:\\users\\user01\\desktop\\a.txt', 'rt')
     오픈 모드 ; r=read, w=write
               t=text, b=binary

+ 읽기
lines = f.readlines()          # 여러줄 읽기. string list로 반환. (마지막에 \n도 포함됨.) 제거하려면, rstrip() 사용
f.close()

for line in lines:
     print(line, end="")     # 라인마지막에 \n이 포함되어 있어서 print에서 자체 \n을 제거하여 출력.

+쓰기
f = open('a.txt', 'wt')
f.write('test\n')
f.write('test2\n')
f.close()

f.seek(위치)
f.tell()    ; 현재 위치

f = open('a.txt', 'wt')
f.write('test\n')
f.write('test2\n')
f.close()

f.seek(위치)
f.tell()    ; 현재 위치






+ OS, sys 모듈

import os
               print (os.getcwd())          ; 현재 디렉터리
os.listdir('c:\python27')        ; dir list
os.rename('a.txt', 'b.txt')     ; rename file
os.chdir('/users/...')          ; cd

os.path.join('/users/aa', 'a.py')          ; 경로 만들기
os.path.expanduser('~')     ; home dir
(dirname, filename) = os.path.split(pathname)          ; directory, filename 분리
(shortname, ext) = os.path.splitext(filename)               ; filename, extension 분리 ; 
abc.py -> abc, .py



++ 현재 소스 디렉터리

srcdir = os.path.dirname( os.path.abspath(__file__))

print('srcdir=', srcdir)



+ listing directory          
import glob                              ; glob module ; shell wild card support!
glob.glob('examples/*.xml')         ; 파일 목록 조회


+ file info
metadata = os.stat('feed.xml')
metadata.st_mtime
123332323.32233223
time.localtime(metadata.st_mtime)     ; time.struct_time( tm_year, tm_mon, tm_mday, tm_hour, tm_min...)
metadata.st_size     ; file size

import humansize
humansize.approximate_size( metadata.st_size)     ; '3.0 KiB'

-전체 경로 얻기
os.path.realpath('feed.xml')          ; full path

os.getcwd() ; 현재 디렉터리
os.chdir(…) ; 현재 디렉터리 이동

os.path.isdir(...)     
os.path.isfile(...)     ; 존재여부 & 파일타입
os.path.isexists(...) ; 존재 여부
os.path.getsize(...)  ; 파일 크기
os.path.split(...')     ; (dir, file) 두 부분으로 잘라준다. 두 부분을 나누는 delimeter는 제외.
os.path.join(dir,filename) ; 두 개를 합쳐준다.
os.sep    ; os seperator 문자. / or \
os.path.normpath(mixed) ; / 와 \가 섞였을때 고쳐준다.

os.getpid()     ; process id
os.getuid()     ; process's real user id
os.getlogin()     ; user id
os.mkdir('c:\\test\\test1\\test2')     ; mkdir(path [,mode])     default mode = 0777, if exist? OSError.

os.makedirs(path[, mode]) ; 중간 경로 생성. if exist, error.  에러 무시하려면?      exist_ok=True를 추가함.
os.makedirs('c:\\test\\test1\\test2', exist_ok=True)




반응형

[Python에서 API서비스 구현하기]


POST로 JSON 요청받아 작업쓰레드를 돌려서 비동기 방식으로 작업하고,

진행 상태를 체크할 수 있는 구조.

Flask 사용.



- 구동 쉘 스크립트 ; server_run.sh

#!/bin/bash
/opt/anaconda3/envs/tensorflow/bin/python server_learn.py

- 서버 ; server_learn.py


from flask import Flask, request
from flask_restful import Resource, Api
from flask.views import MethodView
import json, base64
import string
import random
import os
import threading, time

app = Flask(__name__)
api = Api(app)

# 랜덤스트링 생성하는 함수. 세션키 생성 등
def random_string(size=6, chars=string.ascii_lowercase+string.digits):
return ''.join(random.choice(chars) for _ in range(size))


# 글로벌
g_bworking=False    # 작업 여부.
g_progress = 0        # 진행 상태. 0~100
g_elapsedtime = 0    # 소요 시간. sec
g_workresult={}    # 작업 결과
g_workname=''       # 작업명

# 워커 쓰레드 ; 1~p1까지 sum구하기. 루프 돌때마다 p2 sec만큼 sleep.
def work(myid, p1, p2):
global g_bworking, g_progress, g_workresult, g_elapsedtime
starttime = time.time()

if g_bworking==True:
print('server is busy...')
return 0
g_bworking=True
g_workresult={}
g_progress=0
g_elapsedtime=0
total = 0
for i in range(1, (p1+1)):
total+=i
time.sleep(p2)
print('work : total[',myid,'] = ', total)

g_progress = 100* i / (p1)
g_elapsedtime = time.time() - starttime


endtime = time.time()
g_elapsedtime = endtime - starttime
g_workresult={'total':total, 'until':p1, 'sleep': p2}
g_progress=100
g_bworking=False
return total


class mysum(MethodView):
def get(self):
data = request.args
print(data) # dictionary
return {'name':'test'}

def options(self):
print('options.')
data = request.get_json() # application/json
print(data)
return {'Allow':'PUT,GET,POST'}, 200, \
{'Access-Control-Allow-Origin': '*', \
'Access-Control-Allow-Headers':'Content-Type,Authorization',\
'Access-Control-Allow-Methods': 'PUT,GET,POST'}

def post(self):
global g_workname
# data = request.form
# print(data) # dictionary
data = request.get_json() # application/json
print(data)

if g_bworking==True:
LearnResult = { 'result': 0 }
else:
num = int(data['num'])
slp = int(data['slp'])
g_workname = data['name']
t = threading.Thread(target=work, args=(g_workname, num, slp))
t.start()
LearnResult = {
'result': 1
}
return LearnResult


class status(MethodView):
def get(self):
data = request.args
print(data) # dictionary
if g_progress > 0 :
predtime = g_elapsedtime * 100 / g_progress
else:
predtime = 0
result = { 'work':int(g_bworking),
'workname':g_workname,
'progress':str(g_progress),
'workresult': g_workresult,
'elapsedtime':str(g_elapsedtime),
'remaintime': str(predtime - g_elapsedtime) }
return result

api.add_resource(mysum, '/mysum')
api.add_resource(status, '/status')

if __name__=='__main__':
app.run(host='0.0.0.0', port=18899, debug=True)


- 테스트

http://127.0.0.1:18899/mysum

POSTDATA ; 1~10까지 합 요청. 단계별로 1초씩 쉼.

{

    "num": "10",

    "slp": "1",

    "name": "work1"

}

response: 즉시 아래와 같이 성공 리턴됨.

{

    "result": 1

}



http://127.0.0.1:18899/status

GET

주기적으로 상태 체크 API 호출하여 결과 확인.

{

    "workresult": {

        "until": 10,

        "total": 55,

        "sleep": 1

    },

    "remaintime": "0.0",

    "workname": "work1",

    "elapsedtime": "10.011629581451416",

    "work": 0,

    "progress": "100"

}









+ Recent posts