파이썬 기초
2025-09-26 nipa-ai-agent-파이썬-기초
파이썬 가상 환경 구성
리눅스 서버(Xshell)에 파이썬 가상 환경 구성
개인 서버
# 파이썬 가상환경 기본 패키지 설치
sudo apt install python3-venv
sudo apt install python3-pip
공용 서버
위 기본 패키지는 이미 설치되어 있다고 가정
# 가상 환경 생성
python3 –m venv [가상_환경_이름]
# 가상 환경 활성
source [가상_환경_이름]/bin/activate
# python 실행
python
# 가상 환경 해제
deactivate
앞으로 [개인서버] 라고 붙이지 않는 이상 공용 서버에서 진행
~~/tmp/anacondadownload.sh 이 파일을 폴더 하나 만들어서 복사~~
(base) edu007@vultr:~/sw$ cp /tmp/anacondadownload.sh .
~~bash 사용해서 다운로드~~
(base) edu007@vultr:~/sw$ bash anacondadownload.sh
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 1051M 100 1051M 0 0 225M 0 0:00:04 0:00:04 --:--:-- 222M
기타 필요한 명령어들
# 현재 anaconda 환경에서 생성된 가상환경 목록
conda info --envs
# 가상 환경 활성화
conda activate [가상_환경_이름]
# 가상 환경 비활성화
conda deactivate
# 생성된 가상 환경 삭제
conda remove --name [가상_환경_이름] -all
# 현재 가상 환경에 필요한 패키지를 추가 설치
pip install [패키지명]
PC 환경에서 파이썬 가상 환경 구성
(1) https://www.anaconda.com/download 에서 anaconda 설치파일 download
(2) Anaconda3-2024.10-1-Windows-x86_64.exe를 실행
(3) 윈도우 검색에서 “anaconda” 를 입력 후, “anaconda Prompt”를 실행
(4) anaconda Prompt창에서 python을 입력하여 python 이 정상 설치되었는지 확인
(5) 아래 명령을 입력하여 가상환경을 하나 생성한다. (파이썬버전은 3.10으로 한다.)
conda create –n 가상환경이름 python=파이썬버전
파이썬 기초
기본 문법
변수 선언(타입 지정 불필요)
a = 10
b = 3.14
c = "Python"
d = True
print(type(a)) # <class 'int'>
연산자
- 산술 연산자: //, %, **, …
- 할당 연산자: +=, -=, …
- 비교 연산자: is, is not(객체 식별)
- 멤버십 연산자: in, not in
-
비트 연산자: &, , ^, ~, «, »
a = [1, 2, 3]
b = a
c = [1, 2, 3]
print(a == b) # True
print(a is b) # True
print(a == c) # True
print(a is c) # False
print(5 / 2) # 2.5
print(5 // 2) # 2
print(2 ** 3) # 8
문자열 처리
text = "Hello, Python!"
print(text.strip()) # "Hello, Python!"
print(text.replace("H", "J")) # "Jello, Python!"
print("," in text) # True
name = "Bob"
age = 25
print(f"{name} is {age} years old") # Bob is 25 years old
제어 구조
조건문
score = int(input())
if score >= 90:
print("A")
elif score >= 80:
print("B")
else:
print("C")
반복문
for i in range(5):
print(i)
fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
print(fruit)
count = 0
while count < 5:
print(count)
count += 1
comprehension, enumerate
# list comprehension
squares = [x**2 for x in range(10) if x % 2 == 0]
print(squares) # [0, 4, 16, 36, 64]
# enumerate
fruits = ["apple", "banana", "cherry"]
for idx, fruit in enumerate(fruits, start=1):
print(f"{idx}. {fruit}")
자료구조
numbers = [1, 2, 3, 4, 5]
numbers.append(6) # [1, 2, 3, 4, 5, 6]
numbers.insert(2, 10) # [1, 2, 10, 3, 4, 5, 6]
numbers.remove(3) # [1, 2, 10, 4, 5, 6]
last = numbers.pop() # [1, 2, 10, 4, 5]
print(numbers[1:3]) # [2, 10]
point = (10, 20)
x, y = point # 언패킹
print(x, y) # 10, 20
a = {1, 2, 3}
b = {3, 4, 5}
print(a | b) # {1, 2, 3, 4, 5}
print(a & b) # {3}
student = {"name": "태형", "age": 21, "major": "컴퓨터공학"}
print(student["name"]) # 태형
print(student["age"]) # 21
student["grade"] = "A" # 추가
student["age"] = 21 # 수정
for key in student:
print(f"{key}: {student[key]}")
얕은 복사, 깊은 복사
# 얕은 복사
original = [[1, 2], [3, 4]]
copied = original.copy()
copied[0][0] = 99
print(original) # [[99, 2], [3, 4]] -> 문제!
# 깊은 복사
import copy
original = [[1, 2], [3, 4]]
deep_copied = copy.deepcopy(original)
deep_copied[0][0] = 99
print(original) # [[1, 2], [3, 4]] -> 문제 x
함수
def greet(name, message="안녕하세요."):
return f"{message}, {name}님."
print(greet("철수")) # 안녕하세요, 철수님.
print(greet("영희", "반갑습니다.")) # 반갑습니다, 영희님.
def add(a, b):
return a + b
def sub(a, b):
return a - b
print("덧셈 결과: ", add(10, 5)) # 덧셈 결과: 15
print("뺄셈 결과: ", sub(10, 5)) # 뺄셈 결과: 5
def total_sum(*args):
return sum(args)
print(total_sum(1, 2, 3, 4, 5)) # 15
File
# 파일 입출력
with open("example.txt", "w", encoding="utf-8") as f:
f.write("Python 파일 입출력 테스트\n")
with open("example.txt", "r", encoding="utf-8") as f:
content = f.read()
print(content)
# json 입출력
import json
data = {"name": "Alice", "age": 25}
with open("data.json", "w") as f:
json.dump(data.f)
with open("data.json", "r") as f:
loaded = json.load(f)
print(loaded) # {'name': 'Alice', 'age': 25}
객체
# 객체 선언 및 접근
class Student:
def __init__(self, name):
self.name = name
self.scores = []
def add_score(self, score):
self.scores.append(score)
def average(self):
return sum(self.scores) / len(self.scores)
s = Student("나")
tests = ["국어", "영어", "수학", "과학"]
for test in tests:
s.add_score(int(input(f"{test}의 시험 점수를 입력해 주세요.\n")))
print(f"{s.name}의 평균 시험 점수는 {s.average()}점 입니다.")
# 클래스 변수와 인스턴스 변수
class Student:
count = 0 # 클래스 변수 (모든 인스턴스 공유)
def __init__(self, name):
self.name = name
Student.count += 1
def show(self):
print(f"{self.name} 학생입니다.")
s1 = Student("민지")
s2 = Student("지후")
print("총 학생 수: ", Student.count) # 총 학생 수: 2
# 상속
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
print(f"{self.name}은 ... 소리를 낸다.")
class Dog(Animal):
def speak(self):
print(f"{self.name}가 멍멍 짖는다.")
class Cat(Animal):
def speak(self):
print(f"{self.name}가 야옹 울다.")
d = Dog("바둑이")
c = Cat("나비")
e = Animal("거북이")
d.speak()
c.speak()
e.speak()
소켓
개인 ↔ 개인, 공용 ↔ 공용
import socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('localhost', 5007))
server_socket.listen(1)
print("Echo Server Started!")
client_socket, addr = server_socket.accept()
print(f"Client connected: {addr}")
while True:
# 클라이언트로부터 데이터를 바이트 형태로 받음
data = client_socket.recv(1024)
if not data:
break
# 받은 데이터를 문자열로 변환 (디코딩)
received_msg = data.decode()
print(f"Received: {received_msg}")
# 응답할 메시지를 문자열 형태로 만듦
msg_to_send = f"from server -> {received_msg}"
# 응답 메시지를 바이트로 변환하여(인코딩) 클라이언트에 전송
client_socket.send(msg_to_send.encode())
client_socket.close()
server_socket.close()
import socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('localhost', 5007))
while True:
msg = input("보낼 메세지를 적으세요. (끝내시려면 q를 입력하세요.): \n")
if msg in ["q", "quit", ""]:
break
client_socket.send(msg.encode())
data = client_socket.recv(1024)
print(f"Echo: {data.decode()}")
client_socket.close()
localhost라고 하면 개인↔개인, 공용↔공용 끼리만 된다.
Xshell 창을 두 개 연 다음, 한 쪽에는 echo_server.py, 다른 한 쪽에는 echo_client.py를 실행시킨다.
server → clinet 순서로 실행시켜야 함.
- 파일 보내기
(myvenv) edu007@vultr:~/work/test$ scp -i ~/.ssh/ssh-key-2025-09-24-007.key /home/edu007/work/test/simple_echo_server.py [ubuntu@161.118.158.91](mailto:ubuntu@161.118.158.91):~/work/test/ simple_echo_server.py 100% 535 216.2KB/s 00:00(myvenv) edu007@vultr:~/work/test$ scp -i ~/.ssh/ssh-key-2025-09-24-007.key /home/edu007/work/test/simple_echo_client.py [ubuntu@161.118.158.91](mailto:ubuntu@161.118.158.91):~/work/test/ simple_echo_client.py 100% 400 154.4KB/s 00:00 - 파일들을 한 번에 보내는 법 보내는 파일명을 적을 때 simple_echo*.py 라고 하면 simple_echo로 시작하는 모든 파일을 보냄
개인 ↔ 서버
- 개인 서버에서 방화벽 허용
ubuntu@edu007-20250924-1450:~/work/test$ sudo iptables -I INPUT 1 -p tcp --dport 5000:9000 -j ACCEPT- 한 줄 요약
- “외부에서 이 서버로 들어오는 TCP 방식의 요청 중, 목적지 포트가 5000번부터 9000번 사이인 모든 요청을 방화벽 규칙 맨 위에서 최우선으로 허용해라.”
개인 서버에서 방화벽을 허용해준 다음, 공용 서버 → 개인 서버로 서버, 클라이언트 파일을 둘 다 넘겨주자.
공용 서버에서는 방화벽이 허용 되었다고 가정
cp를 이용해서 server와 client를 각각 복사시켜준다.
import socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('0.0.0.0', 5007))
server_socket.listen(1)
print("Echo Server Started!")
client_socket, addr = server_socket.accept()
print(f"Client connected: {addr}")
while True:
data = client_socket.recv(1024)
if not data:
break
received_msg = data.decode()
print(f"Received: {received_msg}")
msg_to_send = f"from server -> {received_msg}"
client_socket.send(msg_to_send.encode())
client_socket.close()
server_socket.close()
아까는 localhost라고 했는데 '0,0,0,0' 이라고 하면 어디서든지 접속을 허용한다는 뜻이다.
개인 서버의 server 파일과 공용 서버의 server 파일 모두 '0,0,0,0'으로 설정해준다.
import socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('158.247.210.130', 5007))
while True:
msg = input("보낼 메세지를 적으세요. (끝내시려면 q를 입력하세요.): \n")
if msg in ["q", "quit", ""]:
break
client_socket.send(msg.encode())
data = client_socket.recv(1024)
print(f"Echo: {data.decode()}")
client_socket.close()
개인 서버에서 공용 서버로 접속하는 것이기 때문에 connect의 ip 부분을 공용 서버의 ip로 설정해줘야 한다.
import socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('161.118.158.91', 5007))
while True:
msg = input("보낼 메세지를 적으세요. (끝내시려면 q를 입력하세요.): \n")
if msg in ["q", "quit", ""]:
break
client_socket.send(msg.encode())
data = client_socket.recv(1024)
print(f"Echo: {data.decode()}")
client_socket.close()
반대로, 공용 서버에서는 개인 서버로 접속하기 위해 connect의 ip 부분을 개인 서버의 ip로 설정해줘야 한다.
메세지를 파일에 저장하기
개인 → 서버로 보낸 메세지들을 파일에 저장할 수 있다.
추가 기능으로 몇 시에 보냈는지 datetime을 이용해 보기 좋게 표시할 수 있다.
import socket
import datetime
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind(('0.0.0.0', 5007))
server_socket.listen(5)
print("Echo Server Started! Waiting for clients...")
is_shutting_down = False
while not is_shutting_down:
try:
client_socket, addr = server_socket.accept()
print(f"Client connected: {addr}")
try:
while True:
data = client_socket.recv(1024)
if not data:
print(f"Client disconnected: {addr}")
break
received_msg = data.decode()
print(f"Received from {addr}: {received_msg}")
if received_msg.lower() in ["q", "quit"]:
print("Shutdown command received. Server is shutting down.")
is_shutting_down = True
break
now = datetime.datetime.now()
timestamp = now.strftime("[%Y. %m. %d. %H:%M:%S]")
log_message = f"{timestamp} {received_msg}"
with open("socket_message_log.txt", "a", encoding="utf-8") as f:
f.write(log_message + "\n")
echo_msg = f"Log saved: {received_msg}"
client_socket.send(echo_msg.encode())
except ConnectionResetError:
print(f"Connection lost with {addr}")
finally:
client_socket.close()
except KeyboardInterrupt:
print("\nServer is shutting down by Ctrl+C.")
break
except Exception as e:
print(f"A critical error occurred: {e}")
continue
print("Server socket closed. Goodbye!")
server_socket.close()
개인 서버에서 메세지를 보낼 때마다 파일에 저장을 해야 하므로 전체를 while문으로 감싸준다.
timestamp를 현재 시각으로 설정해준 뒤, log_message에 timestamp와 received_msg를 합쳐서 socket_message_log.txt라는 파일에 적어준다.
[2025. 09. 26. 16:37:24] 안녕
[2025. 09. 26. 16:37:48] 오늘은 25년 9월 26일.
[2025. 09. 26. 16:37:59] 내일은 토요일이야
[2025. 09. 26. 16:38:09] 드디어 토요일이라니 주말이 이렇게 소중한줄 몰랐어
[2025. 09. 26. 16:38:10] 잘가
공용 서버의 socket_message_log.txt를 확인해보면 개인 서버에서 보낸 메세지들이 보낸 시각과 함께 저장되는 모습을 볼 수 있다.
ubuntu@edu007-20250924-1450:~/work/test$ python3 simple_echo_client2.py
보낼 메세지를 적으세요. (끝내시려면 q를 입력하세요.):
오늘은 25년 9월 26일.
Echo: Log saved: 오늘은 25년 9월 26일.
보낼 메세지를 적으세요. (끝내시려면 q를 입력하세요.):
내일은 토요일이야
Echo: Log saved: 내일은 토요일이야
보낼 메세지를 적으세요. (끝내시려면 q를 입력하세요.):
드디어 토요일이라니 주말이 이렇게 소중한줄 몰랐어
Echo: Log saved: 드디어 토요일이라니 주말이 이렇게 소중한줄 몰랐어
보낼 메세지를 적으세요. (끝내시려면 q를 입력하세요.):
잘가
Echo: Log saved: 잘가
보낼 메세지를 적으세요. (끝내시려면 q를 입력하세요.):
q