반응형

 

 

 

Python 프로그램을 개발을 할 때 개발 환경을 격리하기 위한 가장 간편한 방법은 어플리케이션 레벨 격리 입니다.

격리 방법은 파이썬 내장 모듈인 venv을 활용하면 됩니다.

 

 

 

  격리(가상) 환경  생성 명령어

# 1. 격리 환경(디렉토리) 생성
python3.<버전> -m venv <격리 환경 이름>

# 2. 격리 환경 활성화
source <격리 환경 이름>/bin/activate

# 3. python3 경로 출력
(<격리 환경 이름>) $ which python3

# 4. 격리 환경 비활성화
(<격리 환경 이름>) $ deactivate

# 5. python3 경로 출력
which python3

 

 

위 명령어를 실행해보면 which python3 명령어를 입력했을 때

격리 환경과 격리되지 않은 환경에서의 python3 경로가 다른 것을 확인할 수 있습니다.

위 명령어를 참고하셔서 Python 프로그램을 개발할 때 안전 하게 격리환경 안에서 개발을 진행하시면 됩니다.

 

 

이 글 이 도움이 되셨기를 바랍니다.

caul334@gmail.com

내용이 유용하셨다면 좋아요&댓글 부탁드립니다.
이 블로그를 이끌어갈 수 있는 강력한 힘입니다!

 

반응형
반응형

 

 

 

 

  Poetry는?

패키지 버전을 관리하지 않아도 손쉽게 Dependency 관리를 가능하게 해주는 도구

즉 poetry를 이용한 프로젝트는 패키지 버전에 종속되지 않고 어느 환경에서든 잘 돌아가게 만들어주는 도구이다.

 

pip를 이용하여 패키지를 설치하면 패키지를 설치할 때마다 requirements.txt를 작성해야 Dependency 문제가 해결됩니다.

하지만 poetry add <package_name> 명령어를 이용하면 따로 패키지 버전을 관리하지 않아도

편하게 Dependency 관리가 가능해집니다.

 

 

  Poetry 설치 방법

1. Ubuntu (linux)
sudo apt install python3-poetry

2. Powershell (Windows)
(Invoke-WebRequest -Uri https://install.python-poetry.org -UseBasicParsing).Content | py -

3. curl 이용
curl -sSL https://install.python-poetry.org | python3

 

 

  Poetry 기본 명령어

# 설치 및 버전 확인
poetry --version

# 새 프로젝트 생성
$ poetry new <project_name>

# 가상환경 실행
$ cd <project_name>
$ poetry shell

# 패키지 설치
$ poetry add <package_name>

 

 

해당 글이 도움이 되셨기를 바랍니다.

 

caul334@gmail.com

내용이 유용하셨다면 좋아요&댓글 부탁드립니다.
이 블로그를 이끌어갈 수 있는 강력한 힘입니다!

 

반응형
반응형

 

 

Ubuntu(Linux) 에서 파이썬 디펜던시와 가상환경 관리를 위해 poetry(포어트리)를 설치하려 했습니다.

 

하지만 아래와 같은 에러를 만났습니다.

 

  에러 메시지 내용

nick@ubuntu:~/python$ pip install --user poetry

error: externally-managed-environment

 

 

  에러 발생 원인

에러 발생 원인은 python 3.11 이상 버전부터 패키지 관리 정책이 변경되어
pip 명령어를 이용한 직접 설치 보다는 Ubuntu 시스템 패키지 관리자인 apt를 통해 패키지를 설치하도록 권장하기 때문입니다.

 

 

  문제 해결 방법

아래 3가지 해결 방법 중 원하는 것을 선택해 해결할 수 있습니다.

 

1. 시스템 패키지 관리자를 이용하여 설치

# 무조건 가상 환경 밖에 설치해야 하는 경우
sudo apt install python3-<package_name>

 

 

2. 프로젝트가 가상환경 안에 있다면 가상환경 안에 설치

# 격리 환경(디렉토리) 생성
python3.<버전> -m venv <가상 환경 이름>

# 격리 환경 활성화
source <가상 환경 이름>/bin/activate

# 패키지 설치
pip install <package name>

 

 

3. curl 유틸리티 이용한 설치

# 유틸리티를 이용한 설치
curl -sSL https://install.python-poetry.org | python3

 

 

 

위 방법을 통해 문제가 해결 되셨기를 바랍니다.

 

caul334@gmail.com

내용이 유용하셨다면 좋아요&댓글 부탁드립니다.
이 블로그를 이끌어갈 수 있는 강력한 힘입니다!

 

반응형
반응형

 

 

회사 업무를 수행하다보면 종종 통계를 위해 메일 제목 또는 메일 내에 있는 특정 문구가 얼마나 있는지 필요한 경우가 있습니다.

 

아래 Python 코드로 그러한 어려움을 해결할 수 있습니다.

 

필요하신 분은 자유롭게 사용하시면 되겠습니다^^

 

Python 코드

# mail_extractor.py
import re
import os
import extract_msg
# pip install extract-msg

def extract_subjects_from_msg(folder_path):
    # 메일에서 제목과 내용 return

    # 결과를 저장할 리스트
    objects = []

    for file_name in os.listdir(folder_path):
        tmp = []
        if file_name.endswith(".msg"):
            file_path = os.path.join(folder_path, file_name)
            try:
                # .msg 파일 열기
                with extract_msg.Message(file_path) as message:

                    # 메일 제목
                    subject = message.subject
                    # 메일 본문
                    body = message.body

                    tmp.append(subject)
                    tmp.append(body)
                    objects.append(tmp)

            except Exception as e:
                print(f"Error reading {file_name}: {e}")

    return objects



def find_content(pattern, body):
    # 일치하는 내용 메일 본문에서 찾기
    content = []

    # 일치 여부
    matches = re.findall(pattern, body)

    # 결과 저장
    for i, match in enumerate(matches, start=1):
        content.append(i)
        content.append(match)

    return content



if __name__ == '__main__':

    # 메일 들이 저장되어 있는 특정 폴더 경로
    folder_path = r"C:\Users\<경로>"

    # 제목, 내용 추출
    results = extract_subjects_from_msg(folder_path)

    # 결과 출력
    for subject, body in results:
        # 제목과 메일 본분만 출력
        print(f"Subject: {subject}, Body: {body}")

        # 찾을 특정패턴이 있는 경우 (아래 코드 활용)
        # 패턴 정의
        pattern = r"\[Rule\]\s*\n(.+)"
        content = find_content(pattern, body)
        print("Subject: {}, Content: {}".format(subject, content))

 

 

 

부족한 부분 또는 개선이 필요한 사항은 댓글 남겨주시기 바라면서

이 글이 도움이 되셨기를 바랍니다.

 

caul334@gmail.com

내용이 유용하셨다면 좋아요&댓글 부탁드립니다.
이 블로그를 이끌어갈 수 있는 강력한 힘입니다!

반응형
반응형

 

해당 글은 Python과  Elasticsearch를 연동함에 있어서 나중에 참고를 목적으로 쓴 글입니다.

 

 

  아래 class Elastic() 구현된 기능

1. Elasticsearch 접속 : connect()

2. Index 크기 검색 : count_index_size()

3. 전체 문서 검색 : search_all_docs()

4. 특정 id에 대한 문서 검색 : search_doc_by_risk_id()

 

# Elasticsearch 관련 모듈 import
from elasticsearch import Elasticsearch


class Elastic:
    # Elastic Search 클래스 선언
    def __init__(self, host, id, pw):
        self.host = host
        self.id = id
        self.pw = pw


    def connect(self):
        # connect to elasticsearch
        es = Elasticsearch(self.host, basic_auth=(self.id, self.pw), verify_certs=False, ssl_show_warn=False)
        if not es.ping():
            raise ValueError("ES Connection failed")
        print('ElasticSearch 연결 완료')
        return es


    def count_index_size(self, es, index_name):
        # count index size
        count = es.count(index=index_name)
        index_size = count.body['count']
        return index_size


    def search_all_docs(self, es, index_name):
        # index에 저장된 모든 docs 검색
        index_size = self.count_index_size(es, index_name)
        search_query = {
            # 모든 docs 검색 및 riskid 기준 내림차순 정렬
            "sort": [
                {
                    "riskid": {
                        "order": "desc"
                    }
                }
            ],
            "size": index_size,
            "query": {
                "match_all": {}
            }
        }

        search_result = es.search(index=index_name, body=search_query)

        return search_result["hits"]["hits"]


    def search_doc_by_risk_id(self, es, index_name, risk_id):
        # index에 저장된 특정id doc 검색
        search_query = {
            "query": {
                "match": {
                    "riskid": risk_id
                }
            }
        }
        search_result = es.search(index=index_name, body=search_query)

        return search_result["hits"]["hits"]


if __name__ == "__main__":

    # 1. Connect ElasticSearch
    elastic = Elastic("https://localhost:9200", "elastic", "elastic_pw")
    es = elastic.connect()

    index_name = "test_index"

    # test_index 내에 있는 모든 문서 검색
    all_docs_list = elastic.search_all_docs(es, index_name)

    # test_index 내에 risk_id 가 12345인 문서 검색
    risk_id = 12345
    doc = elastic.search_doc_by_risk_id(es, index_name, risk_id)

 

 

caul334@gmail.com

내용이 유용하셨다면 좋아요&댓글 부탁드립니다.
이 블로그를 이끌어갈 수 있는 강력한 힘입니다!

반응형
반응형

 

회사 인터넷망 위에서 Python 프로그램을 개발 중인데

Selenium 또는 Selenium-Wire 모듈을 사용하면 반드시 googlechromelabs.github.io  사이트에 접속되어야만 합니다.

하지만 제가 다니는 회사는 프록시 서버를 지나지 않는 이상 Github 사이트에 접속이 불가능하다는 사실...

방화벽 신청까지 해봤지만 결과는 반려 처리ㅜㅜ 어쩔 수 없이 프록시로...

 

제 코드는 3가지 모듈 (selenium-wire, selenium, request)을 사용합니다.

이 경우 Proxy 설정 방법에 관해 공유드리겠습니다.

import certifi
import json
import requests
from seleniumwire import webdriver
from selenium.webdriver.chrome.service import Service


# Selenium 또는 Selnium-Wire를 사용하는 경우
def driver_load():
    # webdriver 로드 #
    chromedriver = ".\\chromedriver.exe"
    service = Service(executable_path=chromedriver)

    seleniumwire_options = {
        "proxy": {
            "http": "<Proxy Server>:<Proxy Port>",
            "https": "<Proxy Server>:<Proxy Port>"
        }
    }

    # Set Options
    options = webdriver.ChromeOptions()
    options.add_argument('--proxy-server=<Proxy Server>:<Proxy Port>')

    # Set up the Chrome WebDriver
    driver = webdriver.Chrome(service=service, seleniumwire_options=seleniumwire_options, options=options)

    return driver


# Requests를 사용하는 경우
def request_post(post_url, params, headers):
    proxies = {
        "http": "<Proxy Server>:<Proxy Port>",
        "https": "<Proxy Server>:<Proxy Port>",
        "no_proxy": "localhost,127.0.0.1 "
    }

    params_json = json.dumps(params)
    response = requests.post(post_url, data=params_json, headers=headers, proxies=proxies, verify=certifi.where())

    return response

 

 

내용이 유용하셨다면 좋아요&댓글 부탁드립니다.
이 블로그를 이끌어갈 수 있는 강력한 힘입니다!

caul334@gmail.com

반응형
반응형

Selenium wire 모듈을 사용하다보면 가끔 POST 요청으로 백그라운드에서 XHR 요청이 발생하는 경우 있습니다.

 

하지만 문제는 POST 요청에 대한 파라미터를 변경한 값을 결과 값으로 가져오고 싶은데 그게 어렵다는 문제입니다ㅠㅠ

 

이런 경우 아래와 같은 코드를 사용하면 Selenium wire 모듈을 통해서도 얼마든지 세션을 유지하면서 Post 요청을 사용할 수 있습니다.

 

  해결책 - Python 코드

from seleniumwire import webdriver
import requests

# WebDriver 설정
options = webdriver.ChromeOptions()
driver = webdriver.Chrome(seleniumwire_options={}, options=options)

# Selenium 모듈로 홈페이지 요청
url = 'https://example.com'
driver.get(url)

# POST 요청을 하는 특정 페이지 요청 값을 수정하여 requests 모듈로 재요청
for idx, request in enumerate(driver.requests):
	if '</api와 같은 홈페이지 uri 값>' in request.url and request.method == 'POST':
		post_url = request.url
		headers = request.headers
		params = {
			'key1': 'val1',
			'key2': 'val2'
		params_json = json.dumps(params)
		response = requests.post(post_url, data=params_json, headers=headers)
		print(response.text)
		break

 

 

caul334@gmail.com

내용이 유용하셨다면 좋아요&댓글 부탁드립니다.
이 블로그를 이끌어갈 수 있는 강력한 힘입니다!

반응형
반응형

 

Python으로 Selenium 모듈을 사용하다가 요청 트래픽과 응답 트래픽을 보기 위해 위해 Selenium Wire를 알게되어

Selenium Wire 모듈을 사용했는데 사용하자마자 역시나 다음과 같은 문제가 이어졌다.

 

Selenium Wire 모듈을 사용하며 특정 사이트에 접속했을 때 아래와 같이 "주의 요함" 또는 "Not Sure" 메시지가 뜬다면...

 

 

 

해결책

1. Selenium wire 홈페이지(https://pypi.org/project/selenium-wire/) 접속

 

 

2. here 클릭하여 ca.crt 파일 다운로드

 

3. 브라우저에 다운받은 인증서 추가

(Chrome 브라우져의 경우) : 설정 > 개인 정보 보호 및 보안 > 보안 > 인증서 관리 > 신뢰할 수 있는 루트 인증 기관 > 가져오기 > 인증서 가져오기 마법사 시작 > 다음 > 파일 경로에 다운 받았던 ca.crt 경로 추가 > 다음

 

 

4. Selenium Wire 재실행 및 확인

인증서를 넣으면! 아래 사진과 같이 "주의 요함" 또는 "Not Sure"메시지가 사라지게 됩니다

 

 

 

 

caul334@gmail.com

내용이 유용하셨다면 좋아요&댓글 부탁드립니다.
이 블로그를 이끌어갈 수 있는 강력한 힘입니다!

반응형
반응형

아이폰 이미지 이름 변경 결과

아이폰 이미지 같은 경우 사진을 백업하게 되면 아래와 같이 IMG_<숫자>.JPG 형식의 이미지가 저장됩니다.

따라서 이 사진이 언제 찍은지 알 수가 없어 사진을 제3의 백업 장소에 백업해서 정리하는 사람에게는 대략 난감한 상황이 아닐 수 없습니다.

저도 몇년치를 몰아서 한꺼번에 백업하려고 하니까 아이폰 사진을 저장하는게 제일 난감하더라구요...

저는 이러한 문제를 Exifread 라는 파이썬 모듈을 사용하여 해결하였습니다.

유용하겠다 생각하여 해결한 한 방법을 공유 드립니다!^^

아이폰 이미지 원본

 

윈도우 기준으로 이미지가 언제 찍혔는지 보는 방법은 사진 파일을 오른쪽 클릭 -> 자세히 -> 원본 에서 확인이 가능합니다.

이 사진은 2016년 08월 30일 오전 10:44에 찍혔네요

이미지 속성

 

아래는 파이썬의 exifread 모듈을 사용해서 해결한 소스코드의 일부분 입니다.

소스코드에도 보이겠지만 사진 파일을 바탕화면 하위에 "1212"라는 폴더에 저장했고

사진 파일 명은 IMG_6066.JPG 입니다.

이미지 변경 python 소스코드

 

그리고 나서 실행만 하면 아래와 같이 사진 이름이 변경되었다는 출력결과가 나옵니다.

실행 결과

 

실제로 해당 폴더에 들어가서 확인해보니 사진 이름이 잘 변경되어 있습니다.

 

아이폰 이미지 이름 변경 결과

 

여러분도 저와 같은 어려움을 겪으셨다면 Python 프로그래밍으로 어려움을 해결하시길 바라겠습니다.

 

아래 소스코드는 위에서 소개해드렸던 소스코드 공유드립니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 반드시 실행 전 pycharm을 관리자 권한으로 실행할 것!
import os
import exifread
 
image_folder_path = '<사진 저장 폴더>'
image_nm = '<사진이름>'
image_abspath = image_folder_path + '\\' + image_nm
print('원본이름: ' + image_nm)
 
# 파일 확장자
ext_idx = image_nm.find('.')
ext = image_nm[ext_idx:]
 
# 사진 파일에서 생성 날짜 메타 데이터 정보 추출할 수 있는 경우
= open(image_abspath, "rb")
tags = exifread.process_file(f)
timedata = str(tags['EXIF DateTimeOriginal'])
f.close()
 
# 변경할 이름 (데이터 파싱)
timedata = timedata.replace(':''')
fname = timedata.replace(' ''_')
 
# 확장자 붙이기
fname = fname + ext
print('변경이름: ' + fname)
 
# 파일 이름 변경
file_oldname = os.path.join(image_folder_path, image_nm)
file_newname = os.path.join(image_folder_path, fname)
os.rename(file_oldname, file_newname)
print('---변경 완료---')
 
cs

 

 

내용이 유용하셨다면 좋아요&댓글 부탁드립니다.
이 블로그를 이끌어갈 수 있는 강력한 힘입니다!

caul334@gmail.com

 

 

반응형
반응형

사진과 동영상 파일을 정리하다 보면 종종 파일 이름이 타임스탬프 형식으로 된 파일이 있습니다.

ex) IMG_1406204196.JPG

 

타임스탬프 형식 이름의 파일이 한 개면 온라인으로 타임스탬프를 시간 형식으로 검색하여 바꾸는 사이트에서 바꾸면 되지만 파일이 여러개일 때에는 프로그래밍을 이용하여 바꾸는게 효율적인 방법이여서 해당 방법 공유드립니다.

 

필요하신분은 아래 코드를 수정하여 사용하시면 됩니다.

 

  코드 로직 설명

1. 파일 이름이 예를 들어 "IMG_1406204196.JPG" 인 경우 정규표현식으로 Timestamp 형식의 문자열을 찾습니다.

2. 프로그램은 파일 이름 중 Timestamp 형식인 1406204196 부분을 찾습니다.

3. 찾은 1406204196 부분을 datetime 모듈을 사용하여 날짜_시간 형식으로 변경합니다.

4. 날짜_시간 형식으로 변경한 결과 20140724_211636 이라는 결과가 반영됩니다.

 

위 코드를 실행하는 경우 아래 사진과 같은 결과를 얻을 수 있습니다.

결론적으로 IMG_1406204196.JPG => 20140724_211636.JPG 로 파일 이름이 변경됩니다.

실행 결과

 

필요하신 분은 아래 소스코드를 복사할 수 있게 해놓았으니

자유롭게 사용하시면 됩니다.

 

  파이썬 소스코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from datetime import datetime
import re
 
# 이미지 이름
image_nm = 'IMG_1406204196.JPG'        # 변경 전 파일명
 
# 파일 확장자 정보
ext_idx = image_nm.find('.')
ext = image_nm[ext_idx:]
 
# 파일 이름 내에 타임스탬프(timestamp) 형식 찾기
timestamp_pat = re.compile('1[0-7]{1}[0-9]{8}')
pat_match = timestamp_pat.findall(image_nm)
print(pat_match)    # 변경 전 타임스탬프
 
if len(pat_match) > 0:
    ut = int(pat_match[0])
    dt = datetime.fromtimestamp(ut).strftime('%Y%m%d_%H%M%S')
    print(dt)        # 변경 후 날짜_시간 형식
    print(dt+ext)    # 변경 후 파일명
cs

내용이 유용하셨다면 좋아요&댓글 부탁드립니다.
이 블로그를 이끌어갈 수 있는 강력한 힘입니다!

caul334@gmail.com

 

 

반응형

+ Recent posts