코드를 작성한 파일의 이름이 sqlite3.py 이기 때문에 되지 않는 것입니다.


파일 이름을 다른 것으로 변경해주면 정상적으로 작동합니다.

블로그 이미지

NCookie

,

(이 글은 파이썬 2.7.12 버전을 기준으로 작성하였습니다.)


여러 문자열을 합치거나 변수와 함께 출력하고자 할 떄 포맷팅을 사용합니다.


그 방법에는 여러 가지가 있을 것입니다.


print "Hello %s" % "World"
print "Hello {}".format("World")
print " ".join("Hello", "World")
print "Hello " + "World"


저는 주로 .format() 을 주로 사용하고 % 를 이용한 포맷팅은 가끔씩 사용합니다.


왜 파이썬에서는 이렇게 여러 방법을 혼용할까요. 사람 헷갈리게.


그 이유는 파이썬 2.5 버전부터  .format()이라는 new syntax가 추가되었기 때문이라고 합니다.


그렇다면 저 둘 중 무엇을 사용하는 것이 좋을까해서 구글링을 해보았더니 명확한 답은 찾을 수 없었습니다.


성능 같은 경우에는 상황에 따라 서로 바뀌기도 하고 .format()은 되지만 % 라는 것도 딱히 보지 못하였습니다. 방법이 다를 뿐 구현은 할 수 있더군요.


결과적으로 답은 못 찾았지만 대신 흥미로운 것들을 알 수 있었습니다.


대표적으로 이런 것들이 있겠네요


li = [12,45,78,784,2,69,1254,4785,984]
print map('the number is {}'.format,li)

print map('some_format_string_%s'.__mod__, some_iterable)


from datetime import datetime,timedelta

once_upon_a_time = datetime(2010, 7, 1, 12, 0, 0)
delta = timedelta(days=13, hours=8,  minutes=20)

gen =(once_upon_a_time +x*delta for x in xrange(20))

print '\n'.join(map('{:%Y-%m-%d %H:%M:%S}'.format, gen))



이런 예시도 있었습니다. 이 예시는 가독성 문제 때문에 .format()에 힘을 실어주는 글이었습니다.


# name 은 (1, 2, 3) 같은 튜플입니다
print "hi there %s" % (name,)   # supply the single argument as a single-item tuple
print "hi there {}".format(name)



어쨌든 제가 내린 결론은 둘 중 어느 방법을 사용하던지 중요한 것은 가독성이라고 생각합니다. 성능이나 구현하는 기능이 그렇게 다르지 않다면요.


결국 이것도 코딩 스타일 중 하나이니까요. 즉, 굳이 특정 방법을 고집할 필요는 없을 것 같습니다.



PS1. timeit 이라는 모듈이 있는데 이걸 이용해서 함수의 처리 시간을 알려주는 것도 있더군요. a라는 함수가 있을 떄 timeit.timeit(a) 와 같이 간단하게 사용할 수 있습니다.


PS2. 로그를 찍을 때 logger 모듈을 사용하는데 포맷팅을 하지 않고 함수에 인자를 전달해서 사용할 수 있습니다.


log.debug("some debug info: %s", some_info)



참고


http://stackoverflow.com/questions/5082452/python-string-formatting-vs-format


http://stackoverflow.com/questions/6960442/difference-between-python-print-format-methods

블로그 이미지

NCookie

,

멀티쓰레딩을 이용하여 여러 개의 클라이언트를 받을 수 있는 소켓 서버를 파이썬으로 구현해 보았습니다. 



server.py

# -*- coding: utf-8 -*-

import threading
import SocketServer
import socket
import sys


class CustomException(Exception):
    """
    Exception 클래스를 상속한 클래스를 만든다
    """
    def __init__(self, value):
        """
        생성할때 value 값을 입력 받음
        """
        self.value = value

    def __str__(self):
        """
        생성할때 받은 value 값을 확인
        """
        return self.value


def raise_exception(err_msg, ip_addr=None):
    """
    예외를 발생하는 함수
    """
    raise CustomException(err_msg)


def print_delimiter():
    print("="*20)


class ThreadedTCPRequestHandler(SocketServer.BaseRequestHandler):

    def handle(self):
        """
        클라이언트와 연결될 때 호출되는 함수
        상위 클래스에는 handle() 메서드가 정의되어 있지 않기 때문에
        여기서 오버라이딩을 해야함
        """
        cur_thread = threading.current_thread()
        print("{} was started for {}"
              .format(cur_thread.getName(), self.client_address[0]))

        while True:
            try:
                self.recv_data = self.request.recv(1024).strip()

                # :/quit 를 입력하거나 데이터가 없다면 루프를 종료
                if self.recv_data == ":/quit" or not self.recv_data:
                    print_delimiter()
                    raise_exception("{} was gone".format(self.client_address[0]))

            except NameError as e:
                print "{0} got an error : {1}".format(self.client_address[0], e)
                self.request.send("Bye")
                break

            except CustomException as e:
                print e
                self.request.send("Bye")
                break

            print "{} wrote:".format(self.client_address[0]),
            print self.recv_data

            # 영어의 소문자 데이터를 receive 하면 대문자로 변환해 send
            self.request.sendall(self.recv_data.upper())

        print("{} was ended for {}"
              .format(cur_thread.getName(), self.client_address[0]))
        print_delimiter()


class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
    pass


if __name__ == "__main__":
    # Port 0 means to select an arbitrary unused port
    HOST, PORT = "0.0.0.0", 3000

    # 소켓 객체 생성
    try:
        server = ThreadedTCPServer((socket.gethostbyname(HOST), PORT), ThreadedTCPRequestHandler)

    except socket.error, msg:
        print "Bind failed. Closing..."
        print "Error code: %s \nError Message: %s"\
          % (str(msg[0]), msg[1])
        sys.exit()

    print "Socket bound on {}".format(PORT)
    ip, port = server.server_address

    # Start a thread with the server -- that thread will then start one
    # more thread for each request
    server_thread = threading.Thread(target=server.serve_forever)
    # Exit the server thread when the main thread terminates
    server_thread.daemon = True
    server_thread.start()
    print "Server loop running in thread:", server_thread.name

    server.serve_forever()

    server.shutdown()
    server.server_close()



client.py

# -*- coding: utf-8 -*-

import socket
import sys

HOST, PORT = "192.168.228.128", 8080
# data = "This will be nickname"  # 실제 서비스에는 닉네임을 전송하자

try:
    # 소켓을 생성 (SOCK_STREAM 은 TCP 소켓을 의미)
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.connect((HOST, PORT))

except socket.error, msg:
    print "Failed to create socket. Error code: %s \nError Message: %s"\
          % (str(msg[0]), msg[1])
    sys.exit(0)
print "Socket created"

# input 값이 :/quit 일 때까지 데이터 입력 및 전송 반복
# :/quit 를 입력하면 socket 종료
while True:

    try:
        data = raw_input("Input : ")

        if data == ":/quit" or not data:
            sock.close()
            break

        try:
            # 서버에 연결하고 데이터를 전송
            sock.sendall(data + "\n")

            # 데이터를 수신하고 소켓 연결을 닫음
            received = sock.recv(1024)

        finally:
            print "Sent:     {}".format(data)
            print "Received: {}".format(received)

    except KeyboardInterrupt as e:
        print e
        data = ":/quit"

sock.close()


블로그 이미지

NCookie

,

이번에는 클라이언트가 특정 단어를 입력하기 전까지 계속해서 데이터를 보낼 수 있는 코드를 짜보았습니다.



server.py


# -*- coding: utf-8 -*-

import SocketServer


def quit_server(client_addr):
    print("{} was gone".format(client_addr))


class MyTCPHandler(SocketServer.BaseRequestHandler):
    """
    The request handler class for our server.

    It is instantiated once per connection to the server, and must
    override the handle() method to implement communication to the
    client.
    """

    def handle(self):
        """
        클라이언트와 연결될 때 호출되는 함수
        상위 클래스에는 handle() 메서드가 정의되어 있지 않기 때문에
        여기서 오버라이딩을 해야함
        """
        self.recv_data = ''

        while True:
            try:
                self.recv_data = self.request.recv(1024).strip()

                # :/quit 를 입력하면 루프를 종료
                if self.recv_data == ":/quit":
                    quit_server(self.client_address[0])
                    break

            except NameError as e:
                print "{0} got an error : {1}".format(self.client_address[0], e)

            finally:
                print "{} wrote:".format(self.client_address[0]),
                print self.recv_data

                # 영어의 소문자 데이터를 receive 하면 대문자로 변환해 send
                self.request.sendall(self.recv_data.upper())


if __name__ == "__main__":
    HOST, PORT = "localhost", 3000

    # 서버를 생성합니다. 호스트는 localhost, 포트 번호는 3000
    server = SocketServer.TCPServer((HOST, PORT), MyTCPHandler)

    print("waiting for connection...")

    # Ctrl - C 로 종료하기 전까지는 서버는 멈추지 않고 작동
    server.serve_forever()



clinet.py


# -*- coding: utf-8 -*-

import socket

HOST, PORT = "localhost", 3000
# data = "This will be nickname"  # 실제 서비스에는 닉네임을 전송하자
data = ''

# 소켓을 생성 (SOCK_STREAM 은 TCP 소켓을 의미)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((HOST, PORT))

# input 값이 :/quit 일 때까지 데이터 입력 및 전송 반복
# :/quit 를 입력하면 socket 종료
while data != ":/quit":
    data = raw_input("Input : ")
    try:
        # 서버에 연결하고 데이터를 전송
        sock.sendall(data + "\n")

        # 데이터를 수신하고 소켓 연결을 닫음
        received = sock.recv(1024)
    finally:
        print "Sent:     {}".format(data)
        print "Received: {}".format(received)

sock.close()



다음에는 멀티쓰레드를 이용하여 한 서버에 여러 클라이언트가 접속할 수 있도록 하는 코드를 올리겠습니다.

블로그 이미지

NCookie

,

파이썬의 SocketServer 모듈은 네트워크 서버의 작성 작업을 간단하게 해줍니다.

(파이썬 3.x 버전에서는 socketserver로 사용할 수 있습니다.)



server.py


# -*- coding: utf-8 -*-

import SocketServer


class MyTCPHandler(SocketServer.BaseRequestHandler):
    """
    The request handler class for our server.

    It is instantiated once per connection to the server, and must
    override the handle() method to implement communication to the
    client.
    """

    def handle(self):
        """
        클라이언트와 연결될 때 호출되는 함수
        상위 클래스에는 handle() 메서드가 정의되어 있지 않기 때문에
        여기서 오버라이딩을 해야함
        """
        self.data = self.request.recv(1024).strip()
        print "{} wrote:".format(self.client_address[0]),
        print self.data
        # 영어의 소문자 데이터를 receive 하면 대문자로 변환해 send
        self.request.sendall(self.data.upper())

if __name__ == "__main__":
    HOST, PORT = "localhost", 3000

    # 서버를 생성합니다. 호스트는 localhost, 포트 번호는 3000
    server = SocketServer.TCPServer((HOST, PORT), MyTCPHandler)

    print("waiting for connection...")

    # Ctrl - C 로 종료하기 전까지는 서버는 멈추지 않고 작동
    server.serve_forever()



clinet.py


# -*- coding: utf-8 -*-

import socket
import sys

HOST, PORT = "localhost", 3000
data = " ".join(sys.argv[1:])

# 소켓을 생성 (SOCK_STREAM 은 TCP 소켓을 의미)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

try:
    # 서버에 연결하고 데이터를 전송
    sock.connect((HOST, PORT))
    sock.sendall(data + "\n")

    # 데이터를 수신하고 소켓 연결을 닫음
    received = sock.recv(1024)
finally:
    sock.close()

print "Sent:     {}".format(data)
print "Received: {}".format(received)



[Errno 10048] 에러는 이미 해당 포트가 사용 중이기 때문에 에러가 발생하는 것입니다. 사용 중인 포트 번호를 바꾸거나 사용 중인 프로세스를 중지해서 해결할 수 있습니다.



출처


https://docs.python.org/2.7/library/socketserver.html#socketserver-tcpserver-example

블로그 이미지

NCookie

,
# -*- coding: utf-8 -*-

li = map(int, raw_input().split(' '))


여러 개의 정수를 문자열로 받아서 공백 단위로 끊은 후에 int형으로 변환시킵니다. 



리스트 자료형에 저장할 수도 있고 a, b = ~~ 처럼 할 수도 있습니다. 다만 변수의 개수가 일치해야겠지만 말입니다.

블로그 이미지

NCookie

,

[파이썬] 클로저

파이썬 2016. 11. 23. 22:16

중첩함수(nested function)

 

함수 안에 함수를 정의한 것을 말합니다.


중첩함수를 통해 default로 enclosing function local scope 변수를 참조할 수 있습니다.



내부 함수와 외부 함수


# -*- coding: utf-8 -*-


def outer_func(msg):

    def inner_func():
        print msg

    return inner_func


inner_func을 내부함수, outer_func를 외부함수라고 합니다.


inner_func 입장에서 outer_func 함수의 지역변수 영역을 enclosing function local scope(바깥 함수 지역 변수 영역) 라고 부릅니다.


 

클로저(closure)란


# -*- coding: utf-8 -*- def outer_func(msg): def inner_func(): print msg return inner_func my_func = outer_func("Megumin is so cute!!") my_func()

Megumin is so cute!!

내부함수가 외부함수의 맥락(context)에 접근할 수 있는 것을 가리킵니다.


inner_func가 outer_func의 지역변수인 msg를 참조하여 출력하는 것을 볼 수 있습니다.


함수를 변수에 저장할 수 있는 이유는 파이썬에서는 함수가 일급 객체(first-class object)이기 때문입니다.


# -*- coding: utf-8 -*-


def outer_func(msg):

    def inner_func():
        print msg

    return inner_func

first_func = outer_func("Megumin is so cute!!")
first_func()

second_func = outer_func("It's true")
second_func()

print
print "outer_func : ", id(outer_func), "\n"
del outer_func

first_func()
second_func()

print
print "first_func : ", id(first_func)
print "second_func : ", id(second_func)
Megumin is so cute!!
It's true

outer_func :  37766872 

Megumin is so cute!!
It's true

first_func :  37766984
second_func :  37767096


outer_func을 삭제해도 first_func가 정상적으로 호출됨을 알 수 있습니다.


이는 함수를 변수에 저장할 때마다 객체를 새롭게 생성하기 때문입니다.

(outer_func, first_func, second_func 모두 id 값이 다릅니다)


즉, first_func와 second_func는 서로 완전히 독립된 객체인 것입니다.



클로저 내에서 enclosing function local scope 변수 Read/Write



클로저에서 enclosing function local scope 변수에 접근할 수 있다면 modify 하는 것도 가능하지 않을까라고 생각할 수 있습니다. 


하지만 그것은 다음과 같은 오류를 보여줄 뿐입니다. 


# -*- coding: utf-8 -*-


def outer_func(msg):

    def inner_func():
        print msg
        msg = "Awesome!!"
        print msg

    return inner_func

first_func = outer_func("Megumin is so cute!!")
first_func()
UnboundLocalError: local variable 'msg' referenced before assignment


첫 번째 print문에서 inner_func 함수 내에서 msg라는 변수는 선언된 적이 없기 때문에 enclosing function local scope에서 찾게 됩니다. 하지만 이 변수는 전역 변수와 마찬가지로 함수 내에서 수정할 수 없습니다. (파이썬 네임스페이스 참고)


그래서 python 3.x 부터는 nonlocal 이라는 키워드를 통해 외부함수 영역의 변수를 modify할 수 있도록 합니다.(nonlocal은 global과 비슷한 개념이라 할 수 있습니다)


python 3.x

# -*- coding: utf-8 -*-

def outer_func(msg):

    def inner_func():
        print(msg)
        nonlocal msg
        msg = "Awesome!!"
        print(msg)

    return inner_func

first_func = outer_func("Megumin is so cute!!")
first_func()
Megumin is so cute!!
Awesome!!


다만, 별로 추천하지는 않다고 합니다.(보충 필요)



대신, python 2.x 에서는 내부 함수의 local variable에 enclosing scope의 변수를 저장하여 사용할 수 있습니다.

# -*- coding: utf-8 -*-


def outer_func(msg):

    def inner_func():
        _msg = msg
        print _msg
        _msg = "Awesome!!"
        print _msg

    return inner_func

first_func = outer_func("Megumin is so cute!!")
first_func()
Megumin is so cute!!
Awesome!!


또는 함수 속성에 변수를 대입해도 가능합니다.

# -*- coding: utf-8 -*-


def outer_func(msg):

    def inner_func():
        inner_func.msg = msg
        print inner_func.msg
        inner_func.msg = "Awesome!!"
        print inner_func.msg

    return inner_func

first_func = outer_func("Megumin is so cute!!")
first_func()
Megumin is so cute!!
Awesome!!



왜 사용할까


● 전역 변수의 사용을 피할 수 있음


● private 속성이 없는 파이썬에서 내부 데이터의 은닉을 할 수 있음


● 하나의 함수로 여러 가지의 함수를 간단히 만들어 낼 수 있도록 해줌


● 기존에 만들어진 함수나 모듈 등을 수정하지 않고도 wrapper 함수를 이용해 커스터마이징할 수 있게 해줌


(상세 설명 보충 필요)



요약



● 클로저란 내부 함수 영역에서 외부 함수 영역의 변수에 접근하는 것을 말함


● 파이썬에서 클로저가 구현 가능한 이유는 함수를 일급 객체로 취급하기 때문


● 클로저 내에서 외부 함수 영역 변수를 수정하기 위해서는 별도의 방법이 필요함


● 데이터 은닉 등의 목적을 위해 사용함



참고


[중첩함수]

https://www.programiz.com/python-programming/closure


[내부 함수와 외부 함수]

http://blog.naver.com/msyang59/220773717531


[클로저란]

https://slipp.net/questions/249

https://opentutorials.org/course/743/6544

http://jonnung.blogspot.kr/2014/09/python-easy-closure.html


[클로저 내에서 enclosing function local scope 변수 Read/Write]

[왜 사용할까]

http://schoolofweb.net/blog/posts/%ED%8C%8C%EC%9D%B4%EC%8D%AC-%ED%81%B4%EB%A1%9C%EC%A0%80-closure/


블로그 이미지

NCookie

,

[파이썬] 가변인자

파이썬 2016. 11. 17. 20:13

파이썬에서는 함수의 인자를 가변적으로 받을 수 있습니다.


만약 여러 개의 숫자를 함수의 인자로 받아 출력하려고 한다면 다음과 같이 코드를 작성할 수 있습니다. 


# -*- coding: utf-8 -*-


def print_num(*numbers):
    for number in numbers:
        print number,

print_num(1, 2, 3, 4)
1 2 3 4


그리고 가변인자는 뒤에 일반인자가 올 수 없으며 하나만 사용할 수 있습니다. 


가변인자를 * 한 개만 사용하여 받으면 튜플 형태로 전달되고 두 개면 딕셔너리 형태로 받아옵니다.


# -*- coding: utf-8 -*-


def print_num(*numbers, **name):
    for number in numbers:
        print number,

    print "\n{0}".format(name)

print_num(1, 2, 3, 4, name="Bob", name2="Julia")
1 2 3 4 
{'name2': 'Julia', 'name': 'Bob'}


블로그 이미지

NCookie

,

파이썬의 퍼스크 클래스 함수에 관한 글입니다. 


퍼스트 클래스 시민에 대한 글을 먼저 보고 오시면 좋을 듯 합니다.


In computer science, a programming language is said to have first-class functions if it treats functions as first-class citizens. Specifically, this means the language supports passing functions as arguments to other functions, returning them as the values from other functions, and assigning them to variables or storing them in data structures.
- 위키피디아


퍼스트 클래스 함수(First Class Function)란 함수를 퍼스트 클래스 시민(first-class citizens)으로 다루는 것을 의미합니다. 


즉, 변수에 담을 수 있고, 함수의 인자로 전달하고 함수의 리턴 값(return value)로 전달할 수 있는 함수입니다.



함수를 퍼스트 클래스 객체로 다룰 수 있게 지원하는 것은 함수형 언어의 특징이라고 합니다. 그렇다면 객체지향 언어인 파이썬(Everything is An Object)에서는 어째서 퍼스트 클래스 함수를 지원할까요?


그래서 주변에 물어봤는데 대부분의 답변은 다양하고 기발한 코딩이 가능하기 때문이라고 합니다. 그에 대한 예시로는 데코레이터, 익명 함수 등이 있을 것입니다.



퍼스트 클래스 함수는 후의 클로저(closure)라는 개념을 공부할 때 이어집니다.



출처


https://en.wikipedia.org/wiki/First-class_function


http://bestalign.github.io/2015/10/18/first-class-object/


http://schoolofweb.net/blog/posts/%ED%8C%8C%EC%9D%B4%EC%8D%AC-%ED%8D%BC%EC%8A%A4%ED%8A%B8%ED%81%B4%EB%9E%98%EC%8A%A4-%ED%95%A8%EC%88%98-first-class-function/


http://blog.doortts.com/135


http://stackoverflow.com/questions/245192/what-are-first-class-objects

블로그 이미지

NCookie

,

위키피디아에서는 first-class citizen을 다음과 같이 정의하고 있습니다.


In programming language design, a first-class citizen (also typeobjectentity, or value) in a given programming language is an entity which supports all the operations generally available to other entities. These operations typically include being passed as an argument, returned from a function, and assigned to a variable.

- Wikikpedia


  프로그래밍 언어 디자인에서 프로그래밍 언어의 first-class citizen는 다른 엔티티가 일반적으로 사용할 수 있는 모든 작업들을 지원하는 엔티티라고 합니다. 이러한 작업들에는 객체 등을 함수의 인자로 넘기거나, 함수에서 반환하고 변수에 할당할 수 있는 것들이 포함되어 있습니다.



first, second class 객체의 개념은 1960년대 Christopher Strachey에 의해 소개되었습니다. 그는 실제로 용어를 엄격하게 정의하지는 않았지만 ALGOL에서 실제 수와 프로시져를 비교하였습니다.


그는 직접 변수에 할당할 수 있는 실수(real number)가 first-class citizen인 것과 달리 그렇지 못한 프로시저는 second-class citizen이라고 하였습니다.



일반적으로 1급 시민의 조건은 다음과 같이 정의한다고 합니다. (참고)

  • 변수(variable)에 담을 수 있다
  • 인자(parameter)로 전달할 수 있다
  • 반환값(return value)으로 전달할 수 있다



블로그 이미지

NCookie

,