안녕하세요.


AWS 상에서 운영을 하다 보니 Cloudwatch를 통하여 모니터링을 많이하게 되었습니다.

더군다나 EC2 위에 올린 MongoDB 모니터링이 필요하여 고민하던 도중 cloudwatch를 이용하기로 결정하고 python으로 개발 하였습니다.


MongoDB의 모니터링은 여러 방법이 많지만,

저는 mongostat / mongotop 을 이용하기로 하였습니다.


MongoDB에 대해서는 아키텍처와 지난번 Real MongoDB 세미나 참석하여 얻은 배움이 전부라 쉽지 않았습니다.


참고로 모니터링 관련 자료는 아래를 보고 툴 대신에 mongostat / top 을 하기로 한 것입니다.

https://docs.mongodb.com/manual/administration/monitoring/


해당 스크립트는 아래 github 스크립트를 custom 한 것입니다.(저작권 관련해서는 어떻게 되는지 모르겠네요..ㅠ)



Mongotop 의 경우도 개발한 mongostat를 커스텀하여 개발한 것입니다.

수집하는 데이터는 기본적으로 현재는 query/ insert / delete / update 관련이며, mongotop 의 경우 주요 테이블을 list하여 수집하였으며, 수집 데이터는 total time / readlock time / writelock time / queries time 을 수집하는 형태로 하였습니다.

또한 1초 단위로 수집한 시간을 뺀 것을 표시하였습니다. (표시 데이터 = 현재 수집한 시간 상태 - 1초전 수집한 데이터)

1회용 수집이기 때문에 crontab 에 등록해서 주기적으로 수집하면 됩니다.

혹여나 문의 사항 있으시면 댓글 또는 happy8510@gmail.com 으로 연락 주시거나 facebook 통해서 연락 주시면 도움 드릴 수 있는 부분에 대해서 도움 드리겠습니다.(개발자가 아니라서 개발 문의 사항은 한계가 있습니다..ㅠㅠ)

cloudwatch에 올리기 위해서는 미리 aws-config 설정 하시기 바랍니다.




* mongostat.py

#!/usr/bin/env python
import argparse
#hyungi unicode incoding
import commands
import datetime, os, time, sys, random
import boto3
 
from pymongo import MongoClient
from pymongo.errors import OperationFailure
from pymongo.errors import ConnectionFailure
from pymongo.errors import ServerSelectionTimeoutError
 
# Version number
PYTHON_MONGOSTAT_VERSION = "0.0.1"
 
# Not authorized error
MONGO2_NOT_AUTH = "unauthorized"
MONGO3_NOT_AUTH = "not authorized"
 
# Authentication failure message
MONGO3_AUTH_FAILUR = "Authentication failed"
 
cloudwatch = boto3.client('cloudwatch')
 
class MongoInstance():
    'Class for mongodb instance'
 
    def __init__(self, host, port, username, password):
        'Initialize the mongodb instance information and create connection to it.'
 
        self.host = host
        self.port = port
        self.username = username
        self.password = password
        self.stats_info = {}
        selfurl='mongodb://%s:%s@%s:%s/admin' % (self.username, self.password, self.host,self.port)
 
        # Create connection to mongodb server
        try:
            #url change
            #self.connection = MongoClient(self.host, self.port)
            self.connection = MongoClient(selfurl)
 
        except ConnectionFailure:
            print "Connection error: create connection to mongodb instance failed."
            exit(1)
 
        # Get the mongodb version
        try:
            server_info = self.connection.server_info()
            self.version = server_info['version']
        except ServerSelectionTimeoutError:
            print "Timeout error: get server information of mongodb instance timeout."
 
        return
 
 
    def try_stats_command(self):
        'Try to execute the serverStatus command to see if authentication required.'
 
        # Execute the serverStatus command at first and handle possible exceptions
        errmsg = server_status = server_status2 = {}
        sleep = 1
        admin = self.connection.admin
        try:
            server_status = admin.command({"serverStatus":1})
            time.sleep(sleep)
            server_status2= admin.command({"serverStatus":1})
           # server_status = ','.joint(tmp_server_status)
        except OperationFailure, op_failure:
            errmsg = op_failure.details
        except:
            print "Execution error: get server status of mongodb instance failed."
            exit(1)
 
        #print server_status
        print 'errmsg :' + str(errmsg)
 
        # Check to see if the mongodb server enables authentication
        if errmsg != {}:
            if errmsg['errmsg'].find(MONGO2_NOT_AUTH) == -1 and errmsg['errmsg'].find(MONGO3_NOT_AUTH) == -1:
                print "Execution error: %s." % errmsg['errmsg']
                exit(1)
            else:
                # Authenticate with the given username and password
                try:
                    admin.authenticate(self.username, self.password)
                except OperationFailure, op_failure:
                    print "Execution error: authenticate to mongodb instance failed."
                    exit(1)
                # Try to execute the serverStatus command again
                try:
                    server_status = admin.command({"serverStatus":1})
                    time.sleep(sleep)
                    server_status2= admin.command({"serverStatus":1})
                except OperationFailure, op_failure:
                    print "Execution error: %s." % op_failure.details['errmsg']
                    exit(1)
 
        thetime = datetime.datetime.now().strftime("%d-%m-%Y.%H:%M:%S")
        cmd = "cat /proc/loadavg"
        out = commands.getstatusoutput(cmd)
        load = out[1].split()[0]
 
        pq = 0
        pi = 0
        pu = 0
        pd = 0
        pgm = 0
 
        = 0
        = 0
        = 0
        = 0
        gm= 0
        glativeW = 0
        glativeR = 0
        # hyungi
        #lok = round(float(server_status[u'globalLock'][u'ratio']),2)
        res = int(server_status[u'mem'][u'resident'])
        vir = int(server_status[u'mem'][u'virtual'])
        mapd = int(server_status[u'mem'][u'mapped'])
 
        #past "sleep" ago status
        pq = int(server_status[u'opcounters'][u'query'])
        pi = int(server_status[u'opcounters'][u'insert'])
        pu = int(server_status[u'opcounters'][u'update'])
        pd = int(server_status[u'opcounters'][u'delete'])
        pgm = int(server_status[u'opcounters'][u'getmore'])
        pcon = int(server_status[u'connections'][u'current'])
 
        #now status
        = int(server_status2[u'opcounters'][u'query'])
        = int(server_status2[u'opcounters'][u'insert'])
        = int(server_status2[u'opcounters'][u'update'])
        = int(server_status2[u'opcounters'][u'delete'])
        gm = int(server_status[u'opcounters'][u'getmore'])
        con = int(server_status2[u'connections'][u'current'])
 
        glactiveW = int(server_status[u'globalLock'][u'activeClients'][u'writers'])
        glactiveR = int(server_status[u'globalLock'][u'activeClients'][u'readers'])
 
        template="%12s%22s%12s%12s%12s%12s%12s%12s%12s%12s%12s%12s%12s%12s"
        header=('hostname''time''insert''query''update',  \
                'delete''getmore','active con',  'resident', \
                'virtual','mapped','load''Act Writer''Act Reader')
 
        cloudwatch.put_metric_data(
            MetricData=[
                {
                    'MetricName''MongoDB-Insert Value',
                    'Dimensions': [
                        {
                            'Name''MongoDB-Primary',
                            'Value''Insert'
                        },
                    ],
                    'Unit''None',
                    'Value': (i-pi)/sleep
                },
                {
                    'MetricName''MongoDB-Query Value',
                    'Dimensions': [
                        {
                            'Name''MongoDB-Primary',
                            'Value''Query'
                        },
                    ],
                    'Unit''None',
                    'Value': (q-pq)/sleep
                },
                {
                    'MetricName''MongoDB-Query Value',
                    'Dimensions': [
                        {
                            'Name''MongoDB-Primary',
                            'Value''Delete'
                        },
                    ],
                    'Unit''None',
                    'Value': (d-pd)/sleep
                },
                {
                    'MetricName''MongoDB-Query Value',
                    'Dimensions': [
                        {
                            'Name''MongoDB-Primary',
                            'Value''Update'
                        },
                    ],
                    'Unit''None',
                    'Value': (u-pu)/sleep
                },
            ],
            Namespace='LogMetrics'
        )
 
        server_statusstr="hostname, thetime, (i-pi)/sleep, (q-pq)/sleep, (u-pu)/sleep, (d-pd)/sleep, (gm-pgm)/sleep, con, res, vir, mapd, load, glactiveW, glactiveR"
 
        print template % header
        print template % (eval(server_statusstr))
 
def mongostat_arg_check(args):
    'Check the given arguments to make sure they are valid.'
 
    # Make sure the rowcount not negative integer
    if args.rowcount and args.rowcount < 0:
        return False"number of stats line to print can not be negative."
 
    # Make sure both username and password should be given, or neither
    if args.username and not args.password:
        return False"only username given, without password."
    if not args.username and args.password:
        return False"only password given, without username."
 
    # Make sure the hostname is valid
    if args.host:
        hostinfo = args.host.split(':')
        if len(hostinfo) > 2:
            return False"invalid mongodb host, only HOSTNAME of HOSTNAME:PORT acceptable."
        if len(hostinfo) == 2:
            try:
                port = int(hostinfo[1])
                if args.port and args.port != port:
                    return False"ports given by port option and host option not match."
            except ValueError:
                return False"invalid mongodb host, the port part not integer."
 
    return TrueNone
 
def mongostat_start(host, port, username, password, rowcount, noheaders, json):
    'Start monitor the mongodb server status and output stats one time per second.'
 
    # Create mongodb instance and make sure we can execute the serverStatus command correctly
    mongo_instance = MongoInstance(host, port, username, password)
    mongo_instance.try_stats_command()
    # print mongo_instance.host, mongo_instance.port, mongo_instance.version, mongo_instance.storage_engine
 
if __name__ == '__main__':
    # Default configurations
    hostname, username, password    = '호스트정보''유저''비밀번호'
    port, rowcount                  = 포트, 0
    noheaders, json                 = FalseFalse
 
    # Define a argument parser for all possible options
    parser = argparse.ArgumentParser(description="Monitor basic MongoDB server statistics.")
    parser.add_argument("--version"help="print the tool version and exit", action="store_true")
    parser.add_argument("--host"help="mongodb host to connect to")
    parser.add_argument("--port"help="server port (can also use --host HOSTNAME:PORT)"type=int)
    parser.add_argument("-u""--username"help="username for authentication")
    parser.add_argument("-p""--password"help="password for authentication")
    parser.add_argument("--noheaders"help="don't output column names", action="store_true")
    parser.add_argument("-n""--rowcount"help="number of stats lines to print (0 for indefinite)"type=int)
    parser.add_argument("--json"help="output as JSON rather than a formatted table", action="store_true")
 
    # Parse all the given options and make sure they are valid
    arguments = parser.parse_args()
    if arguments.version:
        print "Python mongostat version: %s" % PYTHON_MONGOSTAT_VERSION
        exit(0)
    ok, errmsg = mongostat_arg_check(arguments)
    if ok == False:
        print "Argument error: %s" % errmsg
        exit(1)
 
    # Get the given arguments
    if arguments.host:
        hostinfo = arguments.host.split(':')
        hostname = hostinfo[0]
        if len(hostinfo) == 2:
            port = int(hostinfo[1])
    if arguments.port:
        port = arguments.port
    if arguments.username:
        # We make sure username and password must both given or neither in mongostat_arg_check
        username = arguments.username
        password = arguments.password
    if arguments.rowcount:
        rowcount = arguments.rowcount
    if arguments.noheaders:
        noheaders = True
    if arguments.json:
        json = True
 
    # Start the mongostat
    mongostat_start(hostname, port, username, password, rowcount, noheaders, json)


* mongotop.py


#!/usr/bin/env python
import argparse
#hyungi unicode incoding
import commands
import datetime, os, time, sys, random
import boto3
 
from pymongo import MongoClient
from pymongo.errors import OperationFailure
from pymongo.errors import ConnectionFailure
from pymongo.errors import ServerSelectionTimeoutError
 
# Version number
PYTHON_MONGOSTAT_VERSION = "0.0.1"
 
# Not authorized error
MONGO2_NOT_AUTH = "unauthorized"
MONGO3_NOT_AUTH = "not authorized"
 
# Authentication failure message
MONGO3_AUTH_FAILUR = "Authentication failed"
 
cloudwatch = boto3.client('cloudwatch')
#Hyungi / 5 collections select
lstCollection = ['collectionname1','collectionname2','collectionname3','collectionname4','collectionname5']
 
class MongoInstance():
    'Class for mongodb instance'
 
    def __init__(self, host, port, username, password):
        'Initialize the mongodb instance information and create connection to it.'
 
        self.host = host
        self.port = port
        self.username = username
        self.password = password
        self.stats_info = {}
        selfurl='mongodb://%s:%s@%s:%s/admin' % (self.username, self.password, self.host,self.port)
 
        # Create connection to mongodb server
        try:
            #hyungi
            #url change
            #self.connection = MongoClient(self.host, self.port)
            self.connection = MongoClient(selfurl)
 
        except ConnectionFailure:
            print "Connection error: create connection to mongodb instance failed."
            exit(1)
 
        # Get the mongodb version
        try:
            server_info = self.connection.server_info()
            self.version = server_info['version']
        except ServerSelectionTimeoutError:
            print "Timeout error: get server information of mongodb instance timeout."
 
        return
 
 
    def try_stats_command(self):
        'Try to execute the serverStatus command to see if authentication required.'
 
        # Execute the serverStatus command at first and handle possible exceptions
        errmsg = server_status = server_status2 = {}
        sleep = 1
        admin = self.connection.admin
        try:
            server_status = admin.command({"top":1})
            time.sleep(sleep)
            server_status2= admin.command({"top":1})
            #server_status2= admin.command({"serverStatus":1})
        except OperationFailure, op_failure:
            errmsg = op_failure.details
        except:
            print "Execution error: get server status of mongodb instance failed."
            exit(1)
 
        #print server_status
        print 'errmsg :' + str(errmsg)
 
        # Check to see if the mongodb server enables authentication
        if errmsg != {}:
            if errmsg['errmsg'].find(MONGO2_NOT_AUTH) == -1 and errmsg['errmsg'].find(MONGO3_NOT_AUTH) == -1:
                print "Execution error: %s." % errmsg['errmsg']
                exit(1)
            else:
                # Authenticate with the given username and password
                try:
                    admin.authenticate(self.username, self.password)
                except OperationFailure, op_failure:
                    print "Execution error: authenticate to mongodb instance failed."
                    exit(1)
                # Try to execute the serverStatus command again
                try:
                    server_status = admin.command({"top":1})
                    time.sleep(sleep)
                    server_status2= admin.command({"top":1})
                except OperationFailure, op_failure:
                    print "Execution error: %s." % op_failure.details['errmsg']
                    exit(1)
 
        thetime = datetime.datetime.now().strftime("%d-%m-%Y.%H:%M:%S")
        cmd = "cat /proc/loadavg"
        out = commands.getstatusoutput(cmd)
        load = out[1].split()[0]
 
        for strCollist in lstCollection :
            tmpName = 'rocketchat.%s' % strCollist
            print tmpName
            ptotaltime = int(server_status[u'totals'][tmpName][u'total'][u'time'])
            totaltime = int(server_status2[u'totals'][tmpName][u'total'][u'time'])
 
            prelock = int(server_status[u'totals'][tmpName][u'readLock'][u'time'])
            relock = int(server_status2[u'totals'][tmpName][u'readLock'][u'time'])
 
            pwrlock = int(server_status[u'totals'][tmpName][u'writeLock'][u'time'])
            wrlock = int(server_status2[u'totals'][tmpName][u'writeLock'][u'time'])
 
            pquery = int(server_status[u'totals'][tmpName][u'queries'][u'time'])
            query = int(server_status2[u'totals'][tmpName][u'queries'][u'time'])
 
            strMetric_total_Name='MongoDB-%s-%s Value' % (strCollist,'total time')
            strMetric_read_lock_Name='MongoDB-%s-%s Value' % (strCollist,'readLock time')
            strMetric_write_lock_Name='MongoDB-%s-%s Value' % (strCollist,'writeLock time')
            strMetric_query_Name='MongoDB-%s-%s Value' % (strCollist,'queries time')
 
            cloudwatch.put_metric_data(
                MetricData=[
                    {
                        'MetricName': strMetric_total_Name,
                        'Dimensions': [
                            {
                                'Name''MongoDB-Primary-Collections',
                                'Value''total time millisecond'
                            },
                        ],
                        'Unit''None',
                        'Value': (totaltime-ptotaltime)/1000
                    },
                    {
                        'MetricName': strMetric_read_lock_Name,
                        'Dimensions': [
                            {
                                'Name''MongoDB-Primary-Collections',
                                'Value''readLock time millisecond'
                            },
                        ],
                        'Unit''None',
                        'Value': (relock-prelock)/1000
                    },
                    {
                        'MetricName': strMetric_write_lock_Name,
                        'Dimensions': [
                            {
                                'Name''MongoDB-Primary-Collections',
                                'Value''writeLock time millisecond'
                            },
                        ],
                        'Unit''None',
                        'Value': (wrlock-pwrlock)/1000
                    },
                    {
                        'MetricName': strMetric_query_Name,
                        'Dimensions': [
                            {
                                'Name''MongoDB-Primary-Collections',
                                'Value''queries time millisecond'
                            },
                        ],
                        'Unit''None',
                        'Value': (query-pquery)/1000
                    },
                ],
                Namespace='LogMetrics'
            )
 
            template="%12s%12s%12s%12s"
            header=('totime''relock''wrlock''query')
 
            server_statusstr="(totaltime-ptotaltime)/1000, (relock-prelock)/1000, (wrlock-pwrlock)/1000, (query-pquery)/1000"
 
            print template % header
            print template % (eval(server_statusstr))
 
def mongostat_arg_check(args):
    'Check the given arguments to make sure they are valid.'
 
    # Make sure the rowcount not negative integer
    if args.rowcount and args.rowcount < 0:
        return False"number of stats line to print can not be negative."
 
    # Make sure both username and password should be given, or neither
    if args.username and not args.password:
        return False"only username given, without password."
    if not args.username and args.password:
        return False"only password given, without username."
 
    # Make sure the hostname is valid
    if args.host:
        hostinfo = args.host.split(':')
        if len(hostinfo) > 2:
            return False"invalid mongodb host, only HOSTNAME of HOSTNAME:PORT acceptable."
        if len(hostinfo) == 2:
            try:
                port = int(hostinfo[1])
                if args.port and args.port != port:
                    return False"ports given by port option and host option not match."
            except ValueError:
                return False"invalid mongodb host, the port part not integer."
 
    return TrueNone
 
def mongostat_start(host, port, username, password, rowcount, noheaders, json):
    'Start monitor the mongodb server status and output stats one time per second.'
 
    # Create mongodb instance and make sure we can execute the serverStatus command correctly
    mongo_instance = MongoInstance(host, port, username, password)
    mongo_instance.try_stats_command()
    # print mongo_instance.host, mongo_instance.port, mongo_instance.version, mongo_instance.storage_engine
 
if __name__ == '__main__':
    # Default configurations
    hostname, username, password    = '접속ip''유저명''비밀번호'
    port, rowcount                  = 포트, 0
    noheaders, json                 = FalseFalse
 
    # Define a argument parser for all possible options
    parser = argparse.ArgumentParser(description="Monitor basic MongoDB server statistics.")
    parser.add_argument("--version"help="print the tool version and exit", action="store_true")
    parser.add_argument("--host"help="mongodb host to connect to")
    parser.add_argument("--port"help="server port (can also use --host HOSTNAME:PORT)"type=int)
    parser.add_argument("-u""--username"help="username for authentication")
    parser.add_argument("-p""--password"help="password for authentication")
    parser.add_argument("--noheaders"help="don't output column names", action="store_true")
    parser.add_argument("-n""--rowcount"help="number of stats lines to print (0 for indefinite)"type=int)
    parser.add_argument("--json"help="output as JSON rather than a formatted table", action="store_true")
 
    # Parse all the given options and make sure they are valid
    arguments = parser.parse_args()
    if arguments.version:
        print "Python mongostat version: %s" % PYTHON_MONGOSTAT_VERSION
        exit(0)
    ok, errmsg = mongostat_arg_check(arguments)
    if ok == False:
        print "Argument error: %s" % errmsg
        exit(1)
 
    # Get the given arguments
    if arguments.host:
        hostinfo = arguments.host.split(':')
        hostname = hostinfo[0]
        if len(hostinfo) == 2:
            port = int(hostinfo[1])
    if arguments.port:
        port = arguments.port
    if arguments.username:
        # We make sure username and password must both given or neither in mongostat_arg_check
        username = arguments.username
        password = arguments.password
    if arguments.rowcount:
        rowcount = arguments.rowcount
    if arguments.noheaders:
        noheaders = True
    if arguments.json:
        json = True
 
    # Start the mongostat
    mongostat_start(hostname, port, username, password, rowcount, noheaders, json)

반응형

불과 1년전 딥런닝 관련하여 관심을 가지면서 해당 스터디에서 만나 뵙던 분 중 한분인 이재석님이란 분이 계셨다.


비록 2번정도의 스터디 이후 개인적인 일로 더이상 참여를 못했지만 그 때의 인연을 지금까지 페북에서 이어 나갈 수 있었다.


그 때 당시에 python 도 제대로 이해 못하셨던 분이었지만 꾸준히 하시던걸 보며 감명 받았는데, 어느새 챗봇을 만들어 세미나까지 연다고 하시니,

참석을 안할 수가 없었다.(정말 존경하는 분 중의 한분이 되셨다....많이 본받을 분이라고 생각한다)


DBA로써 다양한 지표에 대해서 알고 싶을때나 장애 발생 시 또는 모니터링을 위해 챗봇을 하면 좋다고 막연하게 생각하던 도중이라 더욱더 참가하고 싶었다.


여기의 포스트에는 당시의 ppt 내용 일부와 내가 한 결과물에 대해서 공유만 하려고 한다.

왜냐하면 이 모든게 그냥 소스를 가져와서 나의 카카오봇과 연동한 것 뿐이기 때문이다.



챗봇과 관련한 구글 영상




챗봇은 그리 대단한게 아니지만...만들면 만들수록 대단한거고,

우리가 만드는것은 대단한게 아니라 필요에 의해서 편의를 위해 만드는거라는 내용이 인상 깊었다(-이재석 님)


테스트를 위해 필요한 건 python / flask / ngrok 으로 카카오 봇을 만들수 있었다.


그리고 에코봇을 만들수 있는 소스

https://github.com/software-engineer-mj/chat-bot-seminar


심화로 구글 번역을 이용한 번역봇? 소스


https://github.com/Bricoler/chatbot-seminar


난 여기까지 운이 좋게 테스트를 할 수 있었다.


에코봇


아래는 번역봇이다.


세미나 ppt 는 아무래도 저작권이 있다고 생각하기에 공유는 못하고 깃헙은 이미 공유되어 있는거라 공유해 봤다.


이제 시작이다. 내가 필요한거를 어떻게 공유를 하고 좋을지에 대해서 하나씩 설계해 나갈 예정이다.


그리고 다시 한번 이재석님 감사합니다.

반응형

텐써플로우 첫걸음 이라는 책을 사놓고..

보지도 않고 있다가


오늘에서야 조금씩 보기 시작했다.


DBA로써 내 분야에 대해 공부와 더불어 스트레스를 풀기 위해 데이터 분석도 진행하려고 샀다.



1.변수 간의 관계에 대한 모델
    장점 : 알고리즘의 개념이 복잡하지 않고 다양한 문제에 폭넓게 적용할 수 있음
        - 독립변수 X, 상수항 b와 종속변수 y 사이의 관계를 모델링하는 방법

        - 두 변수 사이의 관계일 경우 단순회귀라고 하며, 여러 개의 변수를 다루는 다중회귀
 

# Tensorflow

# 선형회귀분석

# python 2.7

import numpy as np


num_points = 1000

vectors_set = []


for i in xrange(num_points):

    x1 = np.random.normal(0.0, 0.55)

    y1 = x1 * 0.1 + 0.3 + np.random.normal(0.0, 0.03)

    vectors_set.append([x1, y1])

    

x_data = [v[0] for v in vectors_set]

y_data = [v[1] for v in vectors_set]


%matplotlib inline

import matplotlib.pyplot as plt


plt.plot(x_data, y_data, 'ro')

plt.show()


  1. 비용함수와 경사 하강법 알고리즘
  - 비용함수(오차함수) : 반복이 일어날 때마다 개선되고 있는지 확인하기 위해 얼마나 좋고 나쁜 직선인지를 측정
  - 평균제곱오차 : 실제 값과 알고리즘이 반복마다 추정한 값 사이의 거리를 오차로 하는 값의 평균
  - 경사하강법 : 일련의 매개변수로 된 함수가 주어지면 초기 시작점에서 함수의 값이 최소화되는 방향으로 매개변수를 변경하는 것을 반복적으로 수행하는 알고리즘
    함수의 기울기를 음의 방향 쪽으로 진행하면서 반복적으로 최적화를 수행

    보통 양의 값을 만들기 위해 거리 값을 제곱하며, 기울기를 계산해야 하므로 오차함수는 미분 가능해야 함


#비용 함수와 경사 하강법 알고리즘

import tensorflow as tf

W = tf.Variable(tf.random_uniform([1], -1.0, 1.0))
b = tf.Variable(tf.zeros([1]))
y = W*x_data+b

loss = tf.reduce_mean(tf.square(y-y_data))

optimzer = tf.train.GradienDescenOptimizer(0.5)
train = optimizer.minimize(loass)

#알고리즘 실행

init = tf.global_variables_initializer()

sess = tf.Session()
sess.run(init)

for step in xrange(8):
    sess.run(train)
    
print sess.run(W), sess.run(b)

plt.plot(x_data, y_data, 'ro')
plt.plot(x_data, sess.run(W) * x_data + sess.run(b))
plt.xlabel('x')
plt.ylabel('y')

plt.show()

 



* 사실 이해를 제대로 못했다...하지만 한번 훑고 넘어 가고 다시 한번 보도록 해야겠다.

반응형

개발은 어렵지는 않지만 시간이 오래 걸린다.

특히나 많은 검증을 위해 테스트를 해야되고 이에 대해 오류가 생기거나, 다양한 경우에 대한 대비가 필요하다..


아래 스크립트는 Replication 도중에 Sync가 안맞아 잘못된 데이터나 데이터가 없는 경우에 대해서 확인하여 추가하여 준다.

(오히려 Slave에서 데이가 있으며...Master에서 없는 경우는 해당 사항이 없다.....ㅠ)


로직은 간단하다.


1. file(ini파일로 지정) 를 읽어 해당 파일 내의 테이블 명을 읽는다.(ini 파일 작성 형ㅌㅐ : 테이블1 (줄바꿈) 테이블2 (줄바꿈) ...으로 구분한다.) 

2. 테이블 정보를 가지고  Master에 접속하여 해당 테이블에 대한 PK를 확인 및 테이블 컬럼들을 받아 온다.

3. 다시 해당 테이블 정보를 가지고 full scan한다.

4. Slave에 접속하여 마스터에 대한 테이블 정보( PK)를 가지고 데이터 여부를 확인한다.

5. 해당 데이터가 있으면 Update를 없으면 Insert를 한다.


스크립트 내용은 아래와 같다...스크립트 개발 시 참고하시기를 ....ㅠ

(해당 스크립트에 대한 검증없이 적용 하셨다가 사고가 나도 책임 못집니다........ㅠㅠ 검증의 검증을 하시기를...)

 




#coding: utf-8


import pymysql
import os
import time

now = time.localtime()
todate = "%04d%02d%02d %02d:%02d:%02d" % (now.tm_year, now.tm_mon, now.tm_mday, now.tm_hour, now.tm_min, now.tm_sec)

print "======================================================="
print " Start Time is %s " % todate
print "======================================================="

##### Use Korean Character #######
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
##################################
# Master Info
srv_Master = '마스터IP'

# DBName
srv_DBName = '디비명!!'

# slave1 / slave2 / ...
lst_srv = ['슬레이브IP1','슬레이브IP2',....]
#lst_table = [] -> file 에서 읽어서 사용
#File 형태는 확장자가 ini 이며, 내부에는 한 라인당 하나의 테이블명으로 지정
_filepath = 'INI파일이 저장되어 있는 위치(경로) /home/path...'

def fn_ConnectDB(srv, strDBName) :

db = pymysql.connect(host=srv, port=3306, user='접속유저명', passwd='접속패스워드', db='접속디비명', autocommit=True, use_unicode=True, charset="utf8")

dbCursor = db.cursor()

return dbCursor


def fn_TruncateTable(tmpTable, strDBName) :
for srv in lst_srv: # 2servers
##check Data in Slave DB
curSlave = fn_ConnectDB(srv, srv_DBName)

sqlTruncate = "TRUNCATE TABLE %s.%s" % (strDBName, tmpTable)

print "Nothing Key in table : %s.%s" % (strDBName, tmpTable)
print sqlTruncate

#check curSlave.execute(sqlTruncate)
curSlave.close()


def fn_GetTableInfo(curMaster, strDBName, tmpTable) :
#PK확인
sqlPK = "select COLUMN_NAME, TABLE_NAME, TABLE_SCHEMA " \
" from INFORMATION_SCHEMA.COLUMNS " \
"where " \
" TABLE_NAME='%s' " \
" and TABLE_SCHEMA='%s' " \
" and COLUMN_KEY = 'PRI'" % (tmpTable, strDBName)
curMaster.execute(sqlPK)
#pkResult = curMaster.fetchall()
pkResult = curMaster.fetchall()

#if pkResult == None :
if curMaster.rowcount == 0 :
print 'Nothing Key!!!'
#truncate 진행 -> Key가 없을 경우 truncate 진행
fn_TruncateTable(tmpTable, strDBName)

# 아래처럼 group concat 하면 PK가 무조건 앞에 위치하게
sqlColumns = "SELECT GROUP_CONCAT(COLUMN_NAME) " \
"FROM INFORMATION_SCHEMA.COLUMNS " \
"WHERE " \
" TABLE_NAME = '%s' " \
" AND TABLE_SCHEMA='%s' " % (tmpTable, strDBName)
curMaster.execute(sqlColumns)
# pkResult = curMaster.fetchall()
colResult = curMaster.fetchall()

return(pkResult, colResult)

def fn_WorkingData(tmpMasterData, tmpTable, tmpInfo) :
for srv in lst_srv: # 2servers
##check Data in Slave DB
curSlave = fn_ConnectDB(srv, srv_DBName)
print "==================================================================================="
for tmpData in tmpMasterData :
tmpPK = ''
#curMaster[0]은 무조건 PK값임 / tmpInfo[0] - pk / tmpInfo[1] - all columns
if len(tmpInfo[0]) > 1 :
cntPk = 0
intcolPK = 0
#for colPK in tmpInfo[0][cntPk][0] :
for intcolPK in range(0,len(tmpInfo[0])) :
colPK = tmpInfo[0][intcolPK][0]
if cntPk <> (len(tmpInfo[0])-1) :
tmpPK += colPK + """= \"""" + str(tmpData[cntPk]) + """\" AND """
else :
tmpPK += colPK + """= \"""" + str(tmpData[cntPk]) + """\" """
cntPk += 1
print "Server PK Info : %s" % tmpPK
elif len(tmpInfo[0]) == 1 :
tmpPK = str(tmpInfo[0][0][0]) + """= \"""" + str(tmpData[0]) + """\" """
else :
#PK 가 없을경우 무조건 insert로 취급
tmpPK = " 1=0 "

sqlCheckData = "SELECT 1 FROM %s.%s " \
"WHERE " \
" %s " % (srv_DBName, tmpTable, tmpPK)
curSlave.execute(sqlCheckData)

tmpCheckCnt = curSlave.rowcount

#tmpColName 은 Insert에서 사용하기 위함 ColName 은 Update에서 사용하기 위함
tmpColName = tmpInfo[1][0]
ColName = tmpColName[0].split(',')

if tmpCheckCnt == 0 :
# 데이터 생성을 위한 초기화 작업
j = 0
strData = ""
for i in tmpData:
if j == 0:
strData = """(\"""" + str(i) + """\","""
elif j == (len(tmpData) - 1):
strData += """\"""" + str(i) + """\")"""
else:
strData += """\"""" + str(i) + """\","""
j += 1

#값이 없으니 Insert 진행
sqlInsertSlave = """INSERT INTO %s.%s (%s) VALUES %s""" % (srv_DBName, tmpTable, tmpColName[0], strData)

print ("Insert Query : %s") % sqlInsertSlave

#check 필요 curSlave.execute(sqlInsertSlave)

else :
#값이 있기 때문에 Update 진행
strData = ""
#ColName = tmpInfo[1].split(',')
for i in range(0,len(tmpData)) :
if i == (len(tmpData)-1):
strData += str(ColName[i]) + """ = \"""" + str(tmpData[i]) +"""\""""
else:
strData += str(ColName[i]) + """ = \"""" + str(tmpData[i]) + """\","""

sqlUpdateSlave = """UPDATE %s.%s SET %s WHERE %s""" % (srv_DBName, tmpTable, strData, tmpPK)

print ("Update Query : %s") % sqlUpdateSlave

#Check 필요 curSlave.execute(sqlUpdateSlave)
print "==================================================================================="
def fn_main(curMaster, tmpTable) :

# for tmpTable in lst_table : #60 tables
#tmpInfo[0] = pk column, tmpInfo[1] = All Column(col1,col2...)

tmpInfo = fn_GetTableInfo(curMaster, srv_DBName, tmpTable)

int_Start = 0

#for tCol in range(0, len(tmpInfo[1][0]))

tmpAllCol = tmpInfo[1][0]
#print tmpAllCol -> (u'CODEID,CGID,CG_CID,CODENAME,CODEMEMO,SORTS,USEYN,RDATE',) 이렇게 표현되어 tmpAllCol[0]으로 변환
while True :
#만건씩 잘라서 진행
sqlMasterTable = "SELECT %s " \
"FROM %s.%s " \
"limit %d, 10000" % (tmpAllCol[0], srv_DBName, tmpTable, int_Start)
print ("Limit Query : %s" % sqlMasterTable)

curMaster.execute(sqlMasterTable)

int_Start += 10000
tmpMasterData = curMaster.fetchall()

fn_WorkingData(tmpMasterData, tmpTable, tmpInfo)

if curMaster.rowcount < 10000 :
total_count = int_Start+curMaster.rowcount
print "Last data in Table %s (last select count %d/%d)" % (tmpTable, curMaster.rowcount, total_count)
print "==================================================================================="
break

def fn_read_log(_filename) :
f = open(_filename, 'r')
t_line = f.readlines()
f.close()

f_line = []
#중간에 \n 에 대해서 삭제 후에 진행
for i in t_line:
f_line.append(i.strip())

return f_line

if __name__ == "__main__":

curMaster = fn_ConnectDB(srv_Master, srv_DBName)

filenames = os.listdir(_filepath)
for filename in filenames :
full_filename = os.path.join(_filepath, filename)
ext = os.path.splitext(full_filename)[-1]

if ext == '.ini':
print "Talbes File : " + full_filename
lst_table = fn_read_log(full_filename)
print "Table List : " + str(lst_table)

for aTable in lst_table :
print "Table Name : " + aTable

if aTable <> '' :
fn_main(curMaster, aTable)

now = time.localtime()
finishtime = "%04d%02d%02d %02d:%02d:%02d" % (now.tm_year, now.tm_mon, now.tm_mday, now.tm_hour, now.tm_min, now.tm_sec)

print "======================================================="
print " Start Time is %s " % todate
print " End Time is %s " % finishtime

print "======================================================="


반응형


요즘 3.2 에서 5.6.32 로 Data Migration 이 가능하도록 개발 중이다.


그 중에 잠시 이슈를 정리하고 간다.


MySQL 5.6.32 를 설치한 곳에서 python 으로 


import MySQLdb;


를 하게 되면 아래와 같은 에러가 발생한다.


Traceback (most recent call last):

  File "<stdin>", line 1, in ?

  File "build/bdist.linux-x86_64/egg/MySQLdb/__init__.py", line 19, in ?

  File "build/bdist.linux-x86_64/egg/_mysql.py", line 7, in ?

  File "build/bdist.linux-x86_64/egg/_mysql.py", line 6, in __bootstrap__

ImportError: libmysqlclient.so.10: cannot open shared object file: No such file or directory


확인한 결과 

MySQL 설치된 곳 lib 폴더 내에 해당 libmysqlclient.so.10 파일이 없는 것을 확인 하였다.


검색하다 보니 여기저기 설정하라고 하는데 정작 설치가 되어 있지 않은 것 같아 rpm 으로 설치를 하였다.


아래 내용들은 잘못 되었다...하지만 참고하신 분들이 있을 것 같아서 삭제는 안하고 선을 그었다.



아래는 설정하라는 위치들이다.

/etc/profile

/etc/ld.so.conf


하지만 설치가 우선이라..


아래와 같이 다운 받은 후 설치 해 보자


[root@DBTEST02:/home/backup]# wget ftp://195.220.108.108/linux/Mandriva/official/9.1/i586/Mandrake/RPMS/libmysql10-3.23.55-1mdk.i586.rpm

[root@DBTEST02:/home/backup]# rpm -ivh libmysql10-3.23.55-1mdk.i586.rpm


이러면 설치는 되지만 여전히 import 할 수 없다.


그래서 해당 설치된 위치를 찾아보면 아래와 같다.


[root@DBTEST02:/home/backup]# find / -name libmysqlclient.so.10

/root/src/mysql-3.23.58/libmysql/.libs/libmysqlclient.so.10

/usr/lib/libmysqlclient.so.10


이제 /etc/profile 에 설정을 해 보자.

[root@DBTEST02:/home/backup]# vi /etc/profile


아래 내용을 추가 후 적용해 보자


LD_LIBRARY_PATH=/root/src/mysql-3.23.58/libmysql/.libs/

export LD_LIBRARY_PATH


[root@DBTEST02:/home/backup]# source /etc/profile


이러고 나면 제대로 되는 것을 확인할 수 있다.

하지만.......5.6에 접속이 되지 않는다.


Traceback (most recent call last):

  File "<stdin>", line 1, in ?

  File "build/bdist.linux-x86_64/egg/MySQLdb/__init__.py", line 74, in Connect

  File "build/bdist.linux-x86_64/egg/MySQLdb/connections.py", line 170, in __init__

_mysql_exceptions.OperationalError: (1251, 'Client does not support authentication protocol requested by server; consider upgrading MySQL client')



그렇구나.....다시 검색이 필요하다...



의외로 간단하게 풀었다.


/usr/local/mysql/lib 폴더 내의 libmysqlclient.so.18 을 soft link를 걸어서 생성해 주었다.


[root@DBTEST02:/usr/local/mysql/lib]# ln -s libmysqlclient.so.18.1.0 libmysqlclient.so.10

[root@DBTEST02:/usr/local/mysql/lib]# chown mysql:mysql libmysqlclient.so.10



이후에 session 을 끊은 후 다시 접속하여 확인해 보니 쉽게 통과 했다.


하지만.....다른 에러를 지금 풀고있다.

위의 내용은 쓸데없이 다른 환경설정 건들지 말고 soft link(symbolic link) 로 생성해 주면 된다.


해당 내용은 일단 끝!




추가로 환경설정이 필요해서 추가합니다.


1. cd /etc/ld.so.conf


2. vi로 아무 파일명 생성하여 아래 내용 추가

/usr/local/mysql/lib


ldconfig 를 쳐서 적용


3. vi ~/.bash_profile 

LD_LIBRARY_PATH=/usr/local/mysql/lib

export LD_LIBRARY_PATH


이후 source ~/.bash_profile


한 후 혹시나 하는 마음에 해당 세션 종료 후 다시 접속 후 확인


반응형

현재 MySQL 3.28 로 구성된 Slave를 MySQL 5.6.31 로 업그레이드 작업을 진행 중이다.


Master의 경우 작업 당일날 진행할 예정이고,

Slave의 경우 백업 데이터가 일 단위로 구성되고 있기에 이 부분에 대해 먼저 다른 장비로 Migration 을 진행 하기로 했다.


매일 Dump를 이용해서 작업 하기에는 지루한 작업이 될 것이다.


그래서 매일 백업 데이터를 dump 받아 scp 로 전송 후 다른 장비에서 해당 dump를 이용한 load 및 데이터 건수 비교하는 스크립트를 개발 중이다.


그 중 scp 로 전송하는 방법이 잠시 막혀 공유하고자 한다.





scp 를 이용하는 방법으로 검색하면 twisted ? paramiko_scp ? pexpect ? 등을 설치해서 간편하게 사용하는 방법이 있지만..

가급적이면 설치 등은 피하는 방법을 사용하다 보니

어쩔 수 없이 os.system 이라는 명령문을 사용할 수 밖에 없었다.


os.system은 os에서 사용하는 shell 명령문을 사용 가능하도록 하는 문장인데...

scp 를 하게 되면 먹통이 되는 현상을 확인할 수 있었다.


또한 간단하게 테스트하기 위해서 python에서 직접 os.system 사용하여 scp 를 날리면 비밀번호를 묻는 것을 확인할 수 있었다.

(비밀 번호 묻는게 당연한 이야기 이겠지만....)


여러가지 확인중 ssh 를 이용하여 비밀번호 묻지 않고 바로 전송 하는 방법으로 진행 했더니 정상적으로 전송이 되는 것을 확인할 수 있었다.


아래는 간단하게 ssh 암호 묻지 않는 방법에 대해서 공유해 본다.

(물론 암호 관련하여서는 가급적이면 하지 않는 방법이 최선이며, 꼭 해야 된다면 내부망에서만 가능하도록 하자)



- SSH 암호 없이 접속하는 방법


접속시도하는 (source OS) 에서 

1. ssh key 생성 

 $ ssh-keygen -t rsa

 - /root/.ssh/ 아래에 암호 관련된 파일이 생성


2. ssh 복사

 - /root/.ssh/id_rsa.pub 파일을 cat 으로 열어 내용을 복사


3. Target OS에서 authorized_keys 생성

 - Target (접속하는 서버) 의 /root/.ssh/authorized_keys 파일을 만들어 내용 복사 진행


4. 테스트 진행

 - source OS에서 target OS 으로 접속 진행 테스트

 - port는 1004 라고 가정

 $ ssh -p 1004 192.168.0.2  


암호없이 접속 되면 성공





어쩌면 이것도 ETL 의 개념???과 비슷하지 않을까 싶다. ㅎㅎㅎㅎㅎㅎㅎㅎ


ETL 이란 ? [출처] 위키백과 https://ko.wikipedia.org/wiki/%EC%B6%94%EC%B6%9C,_%EB%B3%80%ED%99%98,_%EC%A0%81%EC%9E%AC

 추출, 변환, 적재(Extract, transform, load, ETL)는 컴퓨팅에서 데이터베이스 이용의 한 과정으로 특히 데이터 웨어하우스에서 다음을 아우른다:


동일 기종 또는 타기종의 데이터 소스로부터 데이터를 추출한다.

조회 또는 분석을 목적으로 적절한 포맷이나 구조로 데이터를 저장하기 위해 데이터를 변환한다.

최종 대상(데이터베이스, 특히 운영 데이터 스토어, 데이터 마트, 데이터 웨어하우스)으로 변환 데이터를 적재한다.


반응형

'Python' 카테고리의 다른 글

[Python Script] Maria DB Table Sync 맞추기  (0) 2017.02.13
[Python] libmysqlclient.so.10 Error  (2) 2016.11.02
[펌][Python] OS 관련 명령어  (0) 2016.10.21
[펌] [python] pass, continue 차이  (0) 2016.03.08
[펌] [python] FTPlib  (1) 2016.03.08

 운영체제(OS)에서 제공되는 기본적인 기능들을 제공.

 

os.getcwd(), os.chdir(path)

 

chdir() 함수는 현재 작업 디렉터리 위치를 변경하며,

getcwd()함수는 현재 작업 디렉터리의 위치를 가져올 때 쓰입니다.

>>> getcwd()

'C:\\Python3'

>>> chdir('Tools')

>>> getcwd()

'C:\\Python3\\Tools'

 

os.access(path, mode)

 

입력받은 <path>에 대해서 <mode>에 해당하는 작업이 가능한지의 여부를 반환합니다.

 

모드(mode)

설명

F_OK

해당 path의 존재 여부를 확인

R_OK

해당 path의 읽기 가능여부 확인

W_OK

해당 path의 쓰기 가능여부 확인

X_OK

해당 path의 실행 가능여부 확인

 

>>> access('.', F_OK)    # existence

True

>>> access('.', W_OK | X_OK | R_OK) # write, exec, read

True

 

os.listdir(path)

 

해당 경로(path)에 존재하는 파일과 디렉터리들의 리스트를 반환합니다.

>>> listdir('.')

['DLLs', 'Doc', 'include', 'Lib', 'libs', 'LICENSE.txt', 'NEWS.txt', 'python.exe', 'pythonw.exe',

'README.txt', 'tcl', 'Tools', 'w9xpopen.exe']

 

os.mkdir(path[, mode])

 

<path>에 해당하는 디렉터리를 생성합니다.

>>> mkdir('test1')

['DLLs', 'Doc', 'include', 'Lib', 'libs', 'LICENSE.txt', 'NEWS.txt', 'python.exe', 'pythonw.exe',

'README.txt', 'tcl', 'test1', 'Tools', 'w9xpopen.exe']

 

os.makedirs(path[, mode])

 

인자로 전달된 디렉터리를 재귀적으로 생성합니다.

이미 디렉터리가 생성되어 있는 경우나 권한이 없어 생성할 수 없는 경우는 예외를 발생합니다.

>>> makedirs('test2/sub1/sub2/leaf')

>>> listdir('test2/sub1/sub2')

['leaf']

>>> makedirs('test2/sub1/sub2/leaf') # 이미 존재하는 디렉터리를 생성하는 경우 예외 발생

Traceback (most recent call last):

File "<pyshell#18>", line 1, in <module>

makedirs('test2/sub1/sub2/leaf')

File "C:\Dev\Python3\lib\os.py", line 152, in makedirs

mkdir(name, mode)

WindowsError: [Error 183] 파일이 이미 있으므로 만들 수 없습니다: 'test2/sub1/sub2/sub3'

 

os.remove(path), os.unlink(path)

 

파일을 삭제 합니다.

>>> remove('test.txt')

>>> unilnk('test.txt')

 

os.rmdir(path)

 

디렉터리를 삭제합니다. 단, 디렉터리는 비어있어야만 합니다.

>>> mkdir('test1')

 

os.removedirs(path)

 

디렉터리를 연달아 삭제합니다.

 

 만약 '윈도우 탐색기'와 같은 애플리케이션으로 'sub1' 디렉터리를 보고 있다면,

removedirs() 함수로 'sub1' 디렉터리를 삭제할 수 없습니다. 탐색기를 종료하고 수행해야 합니다.

# leaf 디렉토리 삭제에 성공하면 차례로 sub2, sub1, test2의 순서로 삭제

>>> removedirs('test2/sub1/sub2/leaf')

 

os.rename(src, dst)

 

src를 dst로 이름을 변경하거나 이동합니다. 파일이나 디렉터리에 대해서 모두 적용 됩니다.

>>> rename('text.txt', 'renamed.txt')

 

os.renames(src, dst)

 

src를 dst로 이름을 변경하거나 이동합니다. rename과 다른점은 이동 시에 필요한 디렉터리들을

자동으로 생성한다는 것입니다.

>>> renames('renamed.txt', 'test_renames/moved.txt')

>>> listdir('test_renames')

['moved.txt']

 

os.stat(path)

 

경로에 해당하는 정보를 얻어옵니다.

아래의 예제와 같이 순차적으로 protection, inode, device, link, user id, group id, size,

last access time, last modified time, last change time 등을 나타냅니다.

(stat() 함수 결과 중 일부는 유닉스/리눅스 시스템에만 해당되는 것도 있습니다)

>>> stat('python.exe')

nt.stat_result(st_mode=33279, st_ino=281474976762468, st_dev=0, st_nlink=1, st_uid=0,

st_gid=0, st_size=26624, st_atime=1321851747, st_mtime=1315097496, st_ctime=1315097496)

 

os.utime(path, times)

 

경로에 해당하는 파일에 대해 액세스 시간(access time)과 수정 시간(modified time)을 <times>로

수정합니다. <times>가 None일 경우는 현재 시간으로 수정합니다. (유닉스의 touch 명령어와 유사)

>>> stat('readme.txt')

nt.stat_result(st_mode=33206, st_ino=281474976762465, st_dev=0, st_nlink=1, st_uid=0,

st_gid=0, st_size=6788, st_atime=1321797957, st_mtime=1315094610, st_ctime=1315094610)

>>> utime('readme.txt', None)

>>> stat('readme.txt')

nt.stat_result(st_mode=33206, st_ino=281474976762465, st_dev=0, st_nlink=1, st_uid=0,

st_gid=0, st_size=6788, st_atime=1321950244, st_mtime=1321950244, st_ctime=1315094610)

 

os.walk(top[, topdown=True[, onerror=None[, followlinks=False]]])

 

top으로 지정된 디렉터리를 순회하며 경로, 디렉터리명을 순차적으로 반환합니다.

다음의 구조로 test_walk, a, b 디렉터리를 만들어 놓고 walk를 실행

 

>>> for path,dirs,files in walk('test_walk'):

    print(path, dirs, files)

    

test_walk ['a', 'b'] []

test_walk\a [] []

test_walk\b [] ['readme.txt']

 

# topdown이 False로 설정된 경우에는 다음과 같이 디렉터리의 끝에서부터 위로 탐색

>>> for path,dirs,files in walk('test_walk', topdown=False):

    print(path, dirs, files)

    

test_walk\a [] []

test_walk\b [] ['readme.txt']

test_walk ['a', 'b'] []

 

os.umask(mask)

 

umask를 설정합니다. 수행하면 이전 mask 값이 반환됩니다. umask가 수행되면

이후 오픈 되는 파일이나 디렉터리에 (mode & ~umask)와 같이 적용됩니다.

 

os.pipe()

 

파이프를 생성합니다. 함수를 실행하면 읽기, 쓰기 전용 파이프의 파일 디스크립터가 반환됩니다.

 

(※ 파이프(pipe)란 프로세스 간 통신을 위한 공유 영역입니다. 여러 프로세스 간에 정보를 주고 받기

위해 만들어지는 공간이며, 하나의 프로세스가 정보를 쓰면 다른 프로세스에서 읽을 수 있습니다)

>>> pipe()

(3, 4)

 

os.fdopen(fd[, mode[, bufsize]])

 

파일 디스크립터를 이용해 파일 객체를 생성합니다.

 

(※ fdopen은 'from os import *'로 import가 안됩니다.

fdopen의 경우 'from os import fdopen'으로 따로 import 해주어야 합니다)

>>> from os import *

>>> from os import fdopen

 

>>> r,w = pipe()

>>> rd = fdopen(r)

>>> rd

<_io.TextIOWrapper name=3 mode='r' encoding='cp949'>

 

os.popen(command[, mode[, bufsize]])

 

인자로 전달된 command를 수행하며 파이프를 엽니다.

(파이썬3 에서는 Popen 클래스의 사용을 권장하지만 그대로 사용할 수도 있습니다)

 

(※ popen은 'from os import *'로 import가 안됩니다. popen의 경우 'from os import popen'으로

import하거나 import os 후 os.popen으로 사용해야 합니다)

>>> from os import popen

 

>>> p = popen('dir', 'r')

>>> p.read()

...<중략>...

2011-09-04 오전 09:51 26,624 python.exe\n

2011-09-04 오전 09:51 27,136 pythonw.exe\n

2011-11-22 오후 05:24 6,788 README.txt\n

2011-11-20 오후 11:06 <DIR> tcl\n

2011-11-20 오후 11:05 <DIR> Tools\n

2011-09-04 오전 09:51 49,664 w9xpopen.exe\n

6개 파일 396,879 바이트\n

9개 디렉터리 72,007,368,704 바이트 남음\n'

 

os.name

 

파이썬이 실행되는 운영체제의 이름을 나타냅니다. (ex: 'nt', 'posix', 'mac'등...)

>>> name

'nt'

 

os.environ

 

환경변수들을 나타내는 사전입니다.

>>> environ

environ({'TMP': 'C:\\DOCUME~1\\ADMINI~1\\LOCALS~1\\Temp',

'COMPUTERNAME': 'WIN2003', 'USERDOMAIN': 'WIN2003',

'COMMONPROGRAMFILES': 'C:\\Program Files\\Common Files', ...<중략>...})

>>> environ['OS']

'Windows_NT'

>>> environ['userprofile']

'C:\\Documents and Settings\\Administrator'

 

os.getpid()

 

현재 프로세스 아이디를 반환합니다.

>>> getpid()

3380

 

os.getenv(varname[, value])

 

환경 변수의 값을 얻어 옵니다. 다만 해당 환경 변수가 없을 경우에는 인자로 전달된 <value>값을

반환합니다. value가 생략되고 해당 환경 변수가 없으면 None을 반환 합니다.

>>> getenv('homepath')

'\\Documents and Settings\\Administrator'

>>> getenv('test', '')

''

 

os.putenv(varname, value)

 

환경변수 <varname>을 <value>로 설정합니다. 자식 프로세스에게 영향을 미칩니다.

>>> putenv('test', '\\tmp\\test')

 

# 자식 프로세스에게 영향을 미치므로, putenv()의 결과 확인.

>>> from os import popen

>>> p = popen('''python -c "import os; print(os.getenv('test'))"''''r')

>>> p.read()

'\\tmp\\test\n'

 

os.strerror(code)

 

에러 코드에 해당하는 에러 메시지를 보여줍니다.

>>> for i in range(0, 44):

print (i, strerror(i))

 

0 No error

1 Operation not permitted

2 No such file or directory

3 No such process

4 Interrupted function call

5 Input/output error

6 No such device or address

7 Arg list too long

8 Exec format error

9 Bad file descriptor

10 No child processes

...<중략>...

 

os.system(command)

 

<command>를 실행하며, 성공한 경우 0을 반환합니다.

[계산기 실행화면]

 

os.startfile(path[, operation])

 

<path>를 os에서 지정된 프로그램으로 실행합니다.

또한 <operation>으로 명시적으로 수행할 프로그램을 지정할 수 있습니다.

 

(※ starfile('LICENSE.txt')의 경우 system("Notepad LICENSE.txt')와 유사하지만 system()을 사용하는

경우에는 파이썬 프로그램의 실행이 잠시 멈추고 system()이 끝나길 기다리게 되고, startfile()은

멈추지 않고 계속 실행됩니다.)

 

os.execl(path, arg0, arg1, ...)

os.execle(path, arg0, arg1, ..., env)

os.execlp(file, arg0, arg1, ...)

os.execlpe(file, arg0, arg1, ..., env)

os.execv(path, args)

os.execve(path, args, env)

os.execvp(file, args)

os.execvpe(file, args, env)

 

위의 함수는 현재 프로세스에서 새로운 프로그램을 수행시키며 리턴은 하지 않습니다.

인자에 따라 여러 가지 exec로 나뉘어지는데, 우선'l'이 붙은 것들은 입력인자들의 수가 정해져

있는 경우이고, 'v'가 붙은 것들은 args라는 튜플로 입력인자를 받습니다. 'e'가 붙은 경우는

환경변수 env를 받느냔 아니냐의 차이이며, 'p'는 환경변수의 path를 이용하는 경우입니다.

>>> execl('C:\\Python3\python''python''-v')

>>> execv('python'('python', '-v'))

>>> execle('C:\Python3\python''python', '-v', {"HOME":"C:\\"})


반응형

원본 : http://wlstnans.tistory.com/101

python 에서의 continue, pass, break 를 정리해보자

for element in some_list: 
    if not element: 
        pass 

for element in some_list: 
    if not element: 
        continue

3문장으로 요약하자면  

1) pass는 단순히 실행할 코드가 없다는 것을 의미한다

2) continue는 다음 순번의 loop를 돌도록 강제하는 것을 의미

3) 이둘은 명백히 다른 구문이다, pass 와는 다르게 continue는 바로 다음 순번의 loop를 돈다


만약 pass 를 타게 되면 A작업은 수행되지만, continue에서는 수행되지 않고 바로 다음 loop 순번으로 돈다.

############################

예제)

for i in [1,2,3]:
        if i:
                print "pass %d" % i
                pass
        print "mjsjinsu pass" # will print after pass


for i in [4,5,6]:
        if i:
                print "pass %d" % i
                continue
        print "mjsjinsu continue"

############################

실행 결과 )

pass 1
mjsjinsu pass
pass 2
mjsjinsu pass
pass 3
mjsjinsu pass
pass 4
pass 5
pass 6


반응형

원본 : http://primrose.tistory.com/37

파이썬으로 FTP서버에 접속하여 여러 작업을 할 때에는 ftplib를 쓰면 편하다.


일단 ftplib을 import 한다


import
ftplib


그 다음엔 FTP서버에 접속을 해야한다. ftplib에서 FTP서버에 접속하게 해 주는 클래스는 FTP클래스로
class ftplib.FTP([host[user[passwd[acct[timeout]]]]])

위와같이 정의되어 있다.

이 중에서 우리가 필요로 하는 것만 설명을 하자면.


host : FTP서버의 IP주소나, 도메인 네임.

user : FTP서버 아이디. 익명으로 접속하려먼 'anonymous' 입력 후 비밀번호를 입력하지 않는다.

passwd : FTP서버의 비밀번호.



이제 위 사항을 기입해서 FTP서버에 접속한다.


import
ftplib

FTP이름 = ftplib.FTP('서버주소','아이디','비밀번호')


무엇인가 잘못 쓴 것이 아니라면 정상적으로 접속이 될 것이다.

접속 된 후에는 ftplib의 함수들을 이용하여 FTP 클라이언트로써의 작업을 수행 할 수 있다.
기본적인 함수들을 소개하자면.

FTP이름.pwd()
: 현재 디렉토리를 보여준다.
FTP이름.cwd(pathname)
: 현재 디렉토리를 바꾼다.

FTP이름.mkd(pathname)
: 현재 디렉토리에 폴더를 만든다.

FTP이름.rmd(pathname)
: 현재 디렉토리의 폴더를 지운다.

FTP이름.size(filename)
: 파일의 크기를 알려준다.
FTP이름.nlst(argument[...])
: FTP서버에서 파일 목록을 가져온다. argument에 아무것도 넣지 않을 경우, 현재 폴더의 파일목록을 가져온다.

FTP이름.retrbinary(commandcallback[maxblocksize[rest]]) 

: FTP서버에서 바이너리모드로 파일을 가져온다.

FTP이름.retrlines(command[callback])

: FTP서버에서 ASCII모드로 파일을 가져온다.

FTP이름.storbinary(commandfile[blocksizecallbackrest])
: FTP서버에 바이너리모드로 파일을 전송한다.
FTP이름.storlines(commandfile[callback])
: FTP서버에 ASCII모드로 파일을 전송한다.
FTP이름.quit()
: FTP서버와의 접속을 끊는다. 에러 발생시엔 FTP이름.close()를 쓴다.



이제 기본적인 함수들을 알았으니 FTP서버에 파일을 전송하는 방법에 대해 설명하겠다.


파일 전송에는 2가지 모드가 있다. 바이너리 모드와 ASCII모드다.


바이너리 모드는 사람이 읽을 수 있는 텍스트 형식의 파일을 제외한 파일들을 전송할 때 쓰고, ASCII모드는 사람이 읽을 수 있는 파일을 전송할 때 쓴다.


일단 바이너리 모드로 파일을 전송해보자. 바이너리 모드로 파일을 전송할 때에는 storbinary 함수에 'STOR' 명령어와 'rb' 모드로 열은 파일 핸들러를 매개변수로 넣어줘야 한다.


import ftplib
FTP이름 = ftplib.FTP('서버주소','아이디','비밀번호')

FTP이름.storbinary( 'STOR' , open('파일이름','rb') )
#'파일이름'은 자기가 전송하려는 파일의 이름

위와같이 하면 FTP서버 내의 현재 디렉토리에 파일이 전송된다.

ASCII모드로 파일을 전송하는 것도 위와 비슷하다. 단지 파일을 여는 방법을 달리해야한다.

import ftplib

FTP이름 = ftplib.FTP('서버주소','아이디','비밀번호')

FTP이름.storlines( 'STOR' , open('파일이름','r') )
#'파일이름'은 자기가 전송하려는 파일의 이름

파일 핸들러를 'r' 모드로 열어서 storlines 함수에 넘겨주면 ASCII모드로 파일이 전송된다.


반응형

+ Recent posts