반응형

 

오늘은 운영 수준에서 따르면 좋은 파이썬 코딩 규칙들 3가지 정도만 소개해드리겠습니다. 출처는 블로그나 책에서 참고했습니다.

 

 

 

(1) 클래스의 내부 메소드는 _(언더바) 로 시작하는 함수명을 짓는다.

 

(2) 주석 코멘트를 잘 작성해준다.

 

(3) iteration 같은 반복자 루프에서는 null 값을 고려한 방어 코드를 작성한다.

 

 

그럼 짧게 코드로 작성해보면 아래와 같습니다.

class MyClass:

    def run(self, my_list: list[str]):

        for something in my_list or []:              (3) iterating 같은 반복자 루프에서는 null 값을 고려한 방어 코드를 작성한다.  

            self._do_something(something)

        

    

    def _do_something(self,something):   (1) 클래스의 내부 메소드는 _(언더바) 로 시작하는 함수명을 짓는다.

        print(something)

    

    def _clean() -> None:     (2) 주석 코멘트를 잘 작성해준다.



       """write clean code .. """



obj = MyClass()

obj.run(["game","movie","runing"])

 

 

 

 

 

감사합니다. 

 

 

 

.

 

 

 
반응형
반응형

오늘도 간단한 파이썬 코딩을 소개해드리겠습니다.

 

k,v 타입의 파이썬 딕셔너리 타입을 쓸 때, 아래 처럼 키의 유무로 인한 분기를 태우는 코드를 많이 작성하실 거에요. 

 

def use_get_dict():
    my_dict={}
    my_dict['a'] = 1
    my_dict['b'] = 2
    my_dict['c'] = 3

    # 일반적인 방법
    if 'a' in my_dict:
        v = my_dict['a']
        print(f"value is {v}")
    else:
        v = 0
        print("It doesn't have key")
    

딕셔너리 타입의 get () 을 이용해서 동일한 분기 처리를 해보겠습니다.

def use_get_dict():
    my_dict={}
    my_dict['a'] = 1
    my_dict['b'] = 2
    my_dict['c'] = 3

    # dict.get() 을 이용한 방법
    v = my_dict.get('a',0)
    print(f"value is {v}")

 

코드가 조금 간결해졌어요.

 

이번에는 swap 을 해볼게요. 예를 들어 정렬을 구현할 때 두 변수의 값을 교환하는 코드를 보통 이렇게 작성할 텐데요. 

 

def swap_with_temp():
    a = 1
    b = 2
    temp = a
    a = b
    b = temp 

    print(f"a = {a}  b={b}")

 

이번에는 아래 예제 코드를 통해서 temp 변수 없이 a, b 의 변수 값을 교환해보겠습니다.

def swap_without_temp():
    a = 1
    b = 2
    a, b = b, a
    print(f"a = {a}  b={b}") 

 

코드가 조금 더 쉬워보여요

 

오늘은 여기까지하겠습니다.

 

끝.

반응형
반응형

pandas란?

  • 데이터 분석을 위한 파이썬 라이브러리
  • 행과 열로 이루어진 데이터 구조를 다룬다.
  • Series 와 Dataframe 자료구조를 사용한다.

 

 

Dataframe 생성

import pandas as pd

#테스트 데이터 dict 생성
data_exam = {
    'name':['a','b','c','d','e'],
    'height':[160,170,180,185,190],
    'age':[23,15,18,19,25],
    'class':['A','B','A','B','A']
}
.
#pandas dataframe 
df=pd.DataFrame(data_exam)

#read from csv file
df=pandas.read_csv(filepath,names=cols,header=None,encoding="cp949")


#Dataframe()으로 호출하면 안되니까 타이핑에 주의하자

df.index
df.columns
df.dtypes

 

Dataframe 다루기

> 특정 컬럼 조회
df['id'] 

> 특정 복수 컬럼 조회.
df[['id','age']] 

> where 절 조건 조회

df[('id'>10)] # ID 10이상만 조회

df.where(filter1 & filter2, inplace = True)


>컬럼 이름 변경
df.rename(columns={'oldName':'newName'},inplace=True)


>Dataframe convert to tuple
tmp = df['id']
mytuple = [x for x in tmp.to_numpy()]

> 컬럭 삭제
df = df.drop(['컬럼이름','col2'],axis=1)
df.dropna(subset=['컬럼이름'],inplace=True)


> 데이터 컬럼 값 변경
df['Gender'].replace('male',1) # Gender 컬럼의 male 값을 1로 대체
df.loc[df['Gender']=='male','Gender']=1



> 특정 컬럼이 널값인 경우 조회
df[df['컬럼1'].isnull()]


> where, query
dt.where(dt.컬럼명1 == 'value').count()['id']

dt.query('컬럼명1 == "value" | 컬럼명2 > 5').count()


> Group By 
dt.groupby('class') #집계할 컬럼
.agg({'height':['count','mean']}) #집계 함수를 적용
.sort_values([('height','mean')]) # 정렬

#agg 에 컬럼 이름을 주면 multiIndex로 생성되는데 () set 형태로 컬럼 이름이 생성된다.


dt.groupby('컬럼이름').size()  그룹별 카운트


> merge

merge_view=view.merge(user,on='uid').merge(product,on='pid')
merge_view=view.merge(user,on='uid').merge(product,on='pid',how='outer')

 

 

Parquet 파일을 Pandas DataFrame 으로 로드하기

rom fastparquet import ParquetFile

# 만약 압축을 풀어야 한다면
import snappy
def snappy_decompress(data, uncompressed_size):
    return snappy.decompress(data)


pf = ParquetFile('sample.snappy.parquet') # filename includes .snappy.parquet extension
df=pf.to_pandas()
pf = ParquetFile('/Users/amore/178309483_20220714_0000_000000000000.parquet')

## 2
df=pd.read_parquet('/Users/amore/appsflyer.snappy.parquet')
df.head()
print(df.head())

 

MySQL 테이블로부터  Pandas DataFrame 으로 로드하기

from sqlalchemy import create_engine
import pandas as pd
import pymysql



db_conn_str = 'mysql+pymysql://User:비밀번호@DB호스트'
mysql_conn = create_engine(db_conn_str)


data = pd.read_sql_table('BOT_USER',mysql_conn)
 
반응형
반응형

 1.데코레이터

많이들 아시겠지만 파이썬에는 데코레이터라는 기능이 있습니다보통 함수나 메소드에 적용하는 기능인데함수나 메서드의 기능을 확장하거나 변경하는 역할을 합니다

 

 

예를 들어 제가 아래와 같이 어떤 처리 함수 my_func를 만들었습니다. 그런데 함수의 성능을 측정하기 위해 함수의 실행시간을 체크하고 싶어요.

 

함수를 수정할 수도 있겠지만, 저라면 runtime_check 라는 데코레이터로 만들어서 여러 함수에 적용해볼 수 있을 것 같습니다. 아래 코드 처럼 데코레이터를 써볼 수 있습니다.

 

    import time 
    def runtime_check(func):
        def func_wrapper():        
            start_time = time.time()
            func()        # 데코레이터를 적용한 함수가 호출되는 부분
            end_time = time.time()
            print(f"runtime : {(end_time - start_time):.4f}")
        return func_wrapper # wrapper 함수 자체를 반환  

    @runtime_check
    def my_func():
        print("function call..")
        time.sleep(2)
    my_func()

    

   

이 처럼 데코레이터 내부에서의 동작은 기존 함수에 로직을 더해 새로운 함수를 만들고 반환하는 방식입니다.

 

 2.데이터클래스

 

데이터클래스는 모듈 수준의 데코레이터라고 할 수 있어요.

 

예제 코드를 보면서 설명해보겠습니다.

 

# 데이터클래스 데코레이터를 쓰기 위한 import 선언 문이구요.
from dataclasses import dataclass, asdict

@dataclass # 데코레이터는 @ 예약어를 씁니다.
class Customer: # 고객 클래스를 선언하구요.
    name: str   # 이름, 나이, 이메일 정도의 클래스 멤버 변수를 만들구요
    age: int
    email: str
# 2개의 객체를 만들어보았습니다.
c1 = Customer("jss1",20,"jss@test.com")
c2 = Customer("jss1",20,"jss@test.com")
# 객체를 출력하고, 객체간의 비교를 해봤습니다. 
# 그리고 마지막으로 클래스 정보를 json 오브젝트로 변환하기 위해 python dictionary 로 변환해보겠습니다.
print(c1)       # Customer(name='jss1', age=20, email='jss@test.com')
print(c2)        # Customer(name='jss1', age=20, email='jss@test.com')
print(c1==c2)    # True  
print(asdict(c1)) # {'name': 'jss1', 'age': 20, 'email': 'jss@test.com'}

 

네 특별한 게 없는 것 같죠..?

그럼 위 코드에서 @dataclass 를 빼고 실행해보시기 바랍니다.

 

그럼 아마도... 아래와 같은 에러가 발생할 거에요

TypeError: Customer() takes no arguments

 

 

그럼 에러를 처리하기 위해 직접 구현해보겠습니다.

class Customer:
    name: str
    age: int
    email: str
    # 객체 초기화를 위한 특별 메소드
    def __init__(self,name,age,email):
        self.name = name
        self.age = age
        self.email = email
    # 객체를 문자열로 표현해주는 특별 메소드
    def __str__(self) -> str:
        return f"name : {self.name} age : {self.age} email : {self.email}"
    # 객체 비교 특별 메소드
    def __eq__(self, value: object) -> bool:
        return True if self.age == self.age else False

 

 

 

위 코드는 객체를 출력하기 위해 __str__ , 객체를 비교하기 위한 __eq__ , 객체의 생성과 초기화를 위해 __init__ 을 구현해습니다.

** asdict()는 dataclass 타입 인스턴스만 인자로 받기 때문에 에러가 여전히 발생할겁니다.

 

결과적으로 데이터클래스 데코터레이터를 이용하면 작성해야 할 코드를 생략할 수 있어요.  데이터클래스 데코레이터를 이용해서 특수 메서드들이 자동으로 추가된 겁니다.

 

필요하면 활용해보세요. :)

 

끝.

반응형
반응형

5년 전 즈음에 실제 제가 면접에서 받았던 손코딩 문제인데, 재미로 공유 드려봅니다.

 

문제는 되게 간단해요.

 

아래 변수 A 와 B 에 담긴 값을 추가 변수 없이(temp) 없이 교환(swap) 해보는 겁니다.

 

A = 10 

B = 5 

 

한 번 풀어보시죠.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

대부분은 임시 변수를 하나 선언해서 swap 하는 방식을 먼저 떠 올릴 것 같은데요. 고민해보면 이런 방법도 있습니다.

정답은 아래 코드입니다. 

A = A+B // 15 

B = A-B // 10 

A = A-B // 5 

 

 

 

4 바이트를 절약할 수 있었네요. 

 

.

 
반응형
반응형

1.레디스 란?

  • Redis = Re(remote) + di(Dictionary) + s (Server )
  • 메모리를 사용하는 db
  • NoSQL, Replication, Master/Slave 구조로 구성이 가능하다.
  • K/V 형태로 데이터 저장.
  • 파일 싱크를 제공
  • 다양한 데이터 타입 제공
  • Strings, Lists, Set, Hashes, Sorted Sets
  • NoSQL 이기 때문에 Table, db, function, row, column 이 존재 하지 않는다
  • 데이터 Interaction 이 Command 를 통해서 이뤄진다.

 

2.왜 레디스?

  • Simple , Flexible
  • Schema, Table, 이 필요없다.
  • Durable
  • Disk 에 데이터를 저장하는 옵션이 있다.
  • 깃헙, 스냅챗, 트위터, 스택오버플로우 등 다양한 서비스에서 사용중

 

** 추가 정보

  • 100만개의 키들을 저장할때 70MB 정도 공간이 소모 된다.
  • 100만개 - 70 MB. 1억개 - 약 7GB,
  • HashType은 매우 효과적으로 인코딩된 사전구조로 되어 있어, Redis 코어 개발자중 한명인 Pieter Noordhuis가 추천함
  • 아이디를 버킷 사이즈로 divid 한 값을 버킷으로 사용. 예를 들어 버킷 사이즈를 1000개로 만든다면?? 아이디를 1000으로 나눈다. >HSET 'mybucket:1155' '11552' '939' >HGET 'mybucket:1155' '11552'
  • HashType 을 이용하여 버킷으로 저장 하는경우 100만 키 - 16MB
  • 데이터를 durable 할 수 있게 파일에 쓰는 옵션이 다양한데, 안전한 옵션일 수록 redis의 속도를 느리게 한다.

 

3.레디스 도커 컨테이너를 이용하여 빠르게 올려보기

 

A) 레디스 구축 명령어 history

#네트워크 생성
$sudo docker network create redis-net

#레디스 서버 
$sudo docker run --name my-redis --network redis-net -p 6379:6379 -v /home/deploy/redis_data:/data -d redis:alpine redis-server --appendonly yes

# 레디스 컨테이너 실행
$sudo docker run --name my-redis --network redis-net \
-p 6379:6379 \
-v ./redis_data:/data \
-v ./redis.conf:/usr/local/etc/redis/redis.conf \
-d redis:alpine redis-server /usr/local/etc/redis/redis.conf


#레디스 CLI
$sudo docker run -it --network redis-net --rm redis:alpine redis-cli -h my-redis

sudo docker run -it --rm redis:alpine redis-cli -h my-redis
$vi redis.conf
requirepass 1111

 

 

B) redis conf

#인증 패스워드 설정
requirepass 1111

#스냅샷 파일 저장 디렉토리 경로 설정
dir /data

#스냅샷 db 파일 이름 설정
dbfilename dump.rdb

#AOF 설정 (Append-Only File) OS 레벨에서 맛탱이 갔을 때를 대비해 
appendonly yes

# 60초마다 1000번 이상 데이터 변경 시 저장
save 60 1

 

C) Redis Client Command

#인증 패스워드 설정
requirepass 1111

#스냅샷 파일 저장 디렉토리 경로 설정
dir /data

#스냅샷 db 파일 이름 설정
dbfilename dump.rdb

#AOF 설정 (Append-Only File) OS 레벨에서 맛탱이 갔을 때를 대비해 
appendonly yes

# 60초마다 1000번 이상 데이터 변경 시 저장
save 60 1
반응형
반응형

개인 노션을 정리하다 궁금해서 신입부터 경력까지 지원했던 서류와 면접을 집계해봤습니다.

 

서류 탈락 141 개 
서류 합격 56 개 
면접 수 31회 

 

 

자소서 내용까지 보니 당시 어색한 정장을 입고, 심호흡을 하며 면접실로 들어갔던 제 모습이 떠오릅니다. 

 

그 때는 노력에 비해 좋은 결과보다 실망스런 결과가 더 많았던 것 같습니다. 노력이 부족했을 수도 있겠지만 그렇게 생각하고 싶지는 않구요.  "열심히 살았구나" 라고 생각하는게 더 좋겠죠.

 

제 경험을 집약해 볼 때 면접 전에 꼭 준비하고 숙지해야 할 내용들을 대충 생각해서 정리해봅니다. 물론 데이터엔지니어 입장에서..

 

  • 다루고 있는 배치 플랫폼/ 스트리밍 플랫폼의 데이터 규모 (신입이라면 다뤄본 데이터 유형들) 
  • 일일 데이터 적재량 또는 배치 프로그램의 규모 
  • DataWarehouse / DataMart / DataLake / ETL / ELT 의 이해
  • 내가 만들었거나 운영중인 데이터 파이프라인을 그림으로 그리고 설명할 준비
  • 내 강점을 집약해서 한 문장으로 표현
  • 지원한 회사의 정보들 그리고 조사 (회사의 기술 사례 발표 또는 시스템 아키텍쳐) 
  • 면접 마지막에 면접관들에게 던질 진문들 ( 인상적인 질문일 수록 좋음 ) 

 

누군가에게 도움이 되길 바랍니다.

 
반응형
반응형

1.streamlit 이란?

파이썬 웹 프레임워크 라이브러리

데이터 사이언스와 머신러닝에 유용한 커스텀 웹 앱을 쉽게 만들어 줄 수 있다고 한다.

시각화와 차트 제공을 위한 다양한 서드파티 모듈이 있다

참고) 공공 데이터  https://www.data.go.kr/index.do

2. 왜 streamlit 을 선택할까 ?

아직 잘은 모르겠지만 내가 봤을때, 데이터 레포트를 웹 페이지로 만들고 싶은데 웹 서버 구축에 대한 부담 없이 텍스트와 마크다운 수준의 코드 만으로 띄우고 싶을때 쓰면 좋을 것 같다.

 

3. streamlit 따라 해보기

a. lib 설치

$ pip install streamlit

 

 

b. app 코드 작성하기

# import module
import streamlit as st
import pandas as pd

# Title
st.title("This is Title line")

# Header
st.header("This is a header")

st.text("This line belongs to a text")



# Markdowns
st.markdown("### This is a markdown")
st.markdown("## This is a markdown")
st.markdown("# This is a markdown")

#Select the subject from the Selectbox
subject = st.selectbox("Subjects: ",['English', 'Hindi', 'Math',
                       'Science'])
# Print the subject
st.write("Your Subject is: ", subject)



# Reading the CSV file
df = pd.read_csv("Startups_Expense.csv")
# Putting title
st.title("View of the Data shown below:")
# To visualize the data
st.write(df)

 

 

c. 실행하기

$ streamlit run app.py

 

 

 

 

d. 그 외 컴포넌트를 알아보려면?

https://streamlit.io/components

 

Components • Streamlit

Streamlit is an open-source Python framework for machine learning and data science teams. Create interactive data apps in minutes.

streamlit.io

 

반응형
반응형

kubectl 명령어 정리 배경

  • 자주 쓰는 것들을 정리해둔 내용인데, 혹시 누군가에게 도움이 될까봐 올려둔다.
  • 개인적인 팁은 kubectl 을 k 라는 alias 로 설정해서 쓰면 편하다
  • 쿠버네티스 리소스 관리 유틸리티인 k9s 를 쓰면 더 편리 할 수 있다. (  URL - https://k9scli.io/ )

 

 

kubectl 명령어 모음

# 네임스페이스 생성
$ kubectl create namespace argocd

# 네임스페이스 를 지정하여 yaml 적용하기
$ kubectl apply -n argocd -f argo-cd.yaml



# 포트 포워드 터널링
$ kubectl port-forward svc/서비스이름 [로컬 포트 : 서비스 포트]

$ kubectl port-forward svc/argocd-server -n argocd 8080:80
$ kubectl port-forward --namespace=ingress-nginx service/ingress-nginx-controller 8080:80


# 이벤트 및 파드 로깅
$kubectl get events

$kubectl get ing

$kubectl get svc,pod,ing


# 애플리케이션 로깅
$ kubectl logs -n [네임스페이스] deployment.apps/파드이름
$ kubectl logs -n airflow deployment.apps/airflow-webserver

# 서비스 어카운트 정보 
$ kubectl get sa
$ kubectl get sa -n kube-system
$ kubectl describe sa [] -n []


# yaml 형식으로 출력하기
$kubectl get sa ebs-csi-controller-sa -n kube-system -o yaml >> sa.yaml

$ kubectl get po -A
# A 옵션을 주면 네임스페이스 전체에 있는 파드가 다 뜬다.


# 파드 서비스 진입
$ kubectl exec [파드이름] /bin/sh
$ kubectl exec [파드이름] -it -- bash
# ssh 진입
$ kubectl exec bdp-web-7849b96cf5-2xzlq -n airflow -it -- bash


# watch를 이용한 모니터링
$ watch -d kubectl get deploy, svc, pods

 

 

kubectl alias 설정

$echo "alias k='/home/ec2-user/bin/kubectl'" >> ~/.bash_profile

$ source ~/.bash_profile
반응형
반응형

1.목표 (What & Why)

  • 지난 번 포스팅에 이어 쿠버네티스 기반 서비스로 동작하도록 구성해본다
  • 쿠버네티스 클러스터, kubectl 을 통한 통신이 준비되어있어야 한다.
  • 순수 애플리케이션 Deploy → 도커 기반의 컨테이너 Deploy → 쿠버네티스 기반 Pod Deploy 를 통해 컨테이너 오케스트레이션을 조금은 이해해본다.

2.과정 (Step)

  • 쿠버네티스 deployment yaml 을 작성한다.
  • Pod 를 배포하고 동작을 확인한다.
  • replica 수를 조정하여 Pod scaling 을 확인해본다.

3.방법 (How)

  • Deployment 를 생성한다.
$ vi deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: common-api-deployment
  labels:
    app: fastapi

spec:
  replicas: 1
  selector:
    matchLabels:
      app: fastapi
  
  template:
    metadata:
      labels:
        app: fastapi
    spec:
      containers:
      - name: containers
        ports:
        - containerPort: 9000
        image: AWS 계정.dkr.ecr.ap-northeast-2.amazonaws.com/demoapp:latest

 

  • kubectl 로 deployment 를 생성한다. 
$ kubectl apply -f deployment.yaml
  • watch 를 통해 Pod, Node, Deployment를 모니터링 할 수 있다.
watch -d kubectl get pod,deploy,node

  • replicas를 수정한다.

  • 서비스를 확인한다.

4. 정리 (summary) 

  • 컨테이너 기술을 이용한다는 건, 의존성과 애플리케이션을 패키징해서 어디서 수행하던 프로그램의 실행과 결과를 보장하게 한다는 것이다.
  • 철학적으로는 격리된 서비스의 실행환경을 만드는 것이고, MSA 를 지향하는 요즘 트렌드에 방향성이 같은 기술이라고 생각한다.
  • 쿠버네티스는 좀 더 나아가서 컨테이너의 무중단 배포, 고가용성 보장과 노드 스케일링, 보안 등의 기능 지원으로 컨테이너 기술의 힘을 더 강하게 해준다. -> 컨테이너 오케스트레이션 이라고 한다.
  • 쿠버네티스는 공부할 것이 많다.
  • 다음에는 시간이 될 지 모르겠지만, emr on eks 의 구성과 karpenter 기반의 spark workload 실행을 포스팅 해보고 싶다. ( 요즘 회사에서 하고 있는 기술이기도 하다. ) 

 

반응형

+ Recent posts