Mac Mojave crontab error 해결책: Operation not permitted

Max OS Mojave 버전 업데이트를 하고나면 크론탭 파일을 수정할수 없는경우가 있을것이다.
이때, 해결책을 알아보자

1. 일단 아래 가이드에 따라 시스템 설정의 해당 메뉴로 이동

시스템 설정 > 보안 및 개인정보 보호 > 개인정보 보호 탭 > 전체 디스크 접근 권한 

System Preference >Security & Privacy > Full Disk Access

--------

2. 내가 사용하는 터미널 앱을 추가해주자

나같은 경우에는 iTerm 을 사용한다.

+ 버튼 클릭 > Application 폴더에 "iTerm2" 선택 후 확인

"+" button > Add iTerm2 from Application folder


3. Restart iTerm2

-End

[Python] Regex sub 함수에서 replace text 로 match 된 값 활용하기 Python

이 예제만 실행시켜 보면 바로 알것이다.

regex = "abc(\d+)|def(\d+)"
text = "abc123456789"
compiled = re.compile(regex)

new_text = re.sub(compiled, r"number:'\1'", text)
print(new_text)

[Python] Regex sub 함수를 활용한 match object 처리 커스터마이징 (특정 그룹 text 수정하기) Python

파이썬의 built-in library 인 re 에는 sub 라는 함수가있다.

아래 링크를 가보면 documentation을 볼수 있는데,
https://docs.python.org/3.6/library/re.html#re.sub

일단, sub 함수를 간단히 설명하자면 Regex 로 잡힌 문자열을 일괄 치환하는 기능을 가지고 있다.
그래서, 나는 로깅용 텍스트를 입력받아 개인정보에 해당하는 영역을 일괄 치환하고자 아래와 같은 함수를 만들었다.

def remove_private_info(text):
private_info_regex = r"'email'\: \['([\w\.\-]+@[\w\.\-]+)'\]|'phone_number'\: \['(\d+)'\]"

def repl_func(m):
text = m.group(0)
groups = m.groups()

for i in range(len(groups)):
if groups[i] is not None:
text = text.replace(groups[i], "***")

return text

return re.sub(private_info_regex, repl_func, text)
이 예제에서는 email 이나 phone_number 에 해당하는 데이터로 Regex에 잡힌 정보만을
*** 이라는 문자열로 일괄 대치 해주고 있다.



카카오톡 공유 링크 meta 정보 캐시삭제

카톡 공유 이미지나 타이틀, 설명 등을 세팅하기위해
웹페이지에 og: 태그를 보통 설정하죠.

개발 중, 이 정보가 변경되었을때, 
https://developers.kakao.com/docs/cache
에서 링크 넣고 삭제 하시면 됩니다

[번역] CELERY 는 어떻게 파이썬의 GIL 문제를 해결하였는가? Python

이 글은 아래 문서를 해석한 것입니다.
https://viralmoon.blogspot.com/2016/06/how-celery-fixed-pythons-gil-problem.html

해석이 어려운 문장은 원문을 같이 적었으니 참고바랍니다.

====================
====================

최근에 나는 Glyph 의 매우 비 생산적인 포스팅을 다시 읽고 있다. 만약에 당신이 그것을 읽어본적이 없다면 가서 한번 읽어봐라. 내가 여기 요약해줄것네, 오리지날을 읽어보는 것도 꽤 가치가 있을것이다.

지난 10년동안 나는 파이썬의 GIL(Global Interpreter Lock) 의 문제점이 무엇인지 파헤쳐 왔다. GIL 과 관련해 진짜 문제가 되는 포인트는 비동기 I/O 였다.
누구나 알고 있듯이, 쓰레드를 관리는 하는것은 꽤 (정형화 되어) 쉬운편이다. 그냥 요청을 받고 쓰레드를 하나 만들면 마법이 펼처진다. 걱정거리가 있다면 공유자원에 대한 것일 것이다.

하지만 당신은 파이썬으로 그것을 효과적으로 할 수 없다. 왜냐면 쓰레드들이 머신 CPU의 core 수와는 상관없이 인터프리터마다 하나씩밖에 존재하지 않는 GIL 을 두고 경쟁해야 하기 때문이다.

그래서 만일 당신이 인텔 core i7 위에서 작업한다고 해도, 파이썬 쓰레드 가지고는 별 성능 향상을 느끼지는 못할것이다.
실제로는 심지어 더 성능이 나빳고, 이게 바로 파이썬 3.1 버전 이전 GIL 의 문제점이었다. (멀티 코어 환경에서의 쓰레딩은 코드 동작을 더 느리게 만들었고, 실제 동작은 더 구렸다.)


asynchronous I/O 가 문제인가? (Is asynchronous I/O a problem?)

근래의 프로그래밍에서 대부분의 이슈들이 I/O 문제로 수렴된다. 참 클래식한 답변이다.

예를들어, DB에서 데이터를 읽어오는 것은 I/O 작업이다. - 당신은 데이터를 읽어와 fetch 할때까지 system 은 뭔가 다른 작업을 할수 있다. 예를들어 다른 요청을 처리한다든지... 몇 년전, 내가 Twisted project 에 맞닥뜨렸을때, 그것(파이썬의 I/O문제)은 모든 면에서 나를 참 힘들게 했었다. (= Years ago when I encountered the Twisted project that was the reasoning for all the hoops it put you through.)

그 (내가겪은) 문제의 원인이 될수 있는 상황들로 파이썬 asyncio 측에서 말한 내용은 아래와 같다.
(= The reasoning for asyncio's recent addition to Python is)

"싱글 스레드에 coroutine을 활용한 동시성 코드를 작성하는것, 소켓 및 다른 자원들에 대해 multiplexing I/O 접근이 이루어 지는것, 네트워크 클라이언트와 서버를 운영하는것"

여기엔 내가 얘기해주고 싶은 몇가지 전제조건이 있다.
- 싱글스레드 환경에 동시성코드를 작성할 필요가 있어야 함.
- 꽤 자주 multiplex I/O 가 필요해야함
- coroutine 을 사용해야함

무엇보다도, 우리가 정말 싱글 스레드 + 동시성 코드가 필요할까?
지난 10년간 나는 누군가 "이 코드는 concurrent 하지만 single threaded 해야합니다" 라고 콕 찝어 말하는 케이스를 본적이 없다.
내 생각에 여기서 중요한 것은 우리가 동시성을 원하고 그것이 (진정한 동시성을 가질 수는 없는) GIL 과 관련하여 가장 흔한 인자라는 것입니다. (=I think the idea here is really that we want concurrent and that's the most often argument we see with regard to the GIL - that we can't have true concurrency.)

내가 최근에 명백히 깨달은 것은 우리는 정말 동시성이 필요 없다는 것입니다. - 곧 다시 이 주제로 되돌아올텐데, 그 전에 코루틴 녀석을 제껴버리기 위해 두 단어로 된 가정을 좀 하겠습니다.
사람들이 코루틴을 필요로 할까요? 네 하지만 production 코드는 아닙니다. 제가 너무 제 의견을 고집하는것일수도 있지만, 저는 여러 언어로 동시성 코드를 작성했으나 단 한번도 코루틴만큼 가독성이 떨어지는 코드를 본 적이 없습니다
만약에 코드가 읽혀지기를 위해 쓰여진 것이라면, 코루틴은 당신 눈에서 피눈물이 나게 하기 위해 쓰여진 것입니다( 그만큼 알아 보기 힘들다는 뜻인듯)

또한 cooperative concurrency, 즉 코루틴은 꽤 오래전에 버려졋습니다. 왜그럴까요?
왜냐하면 코루틴의 기본적인 전제는 "협력"이기 때문입니다.
선점형 동시성은 공평한 자원의 사용을 강요, 아니 최소 지향합니다.
하지만 코루틴은 그럴수가 없죠 - 만약 당신의 코루틴이 (자원을 점유하고 액세스를) 막으면, 그것은 막히고 당신은 그냥 기다려야 합니다. 그리고 당신의 스레드는 다른 모든 코루틴과 함께 기다려야 합니다.
그것이 실제로 코루틴의 가장 큰 문제입니다.

만약 당신의 문제가 쉘스크립트로 피보나치 숫자계산 코드를 만들기 어려운 것이라면 차라리 그게 낫습니다. 하지만 이 추운곳(지옥같은 실서비스? 같은느낌)에서는 서버가 다운되고, 커넥션 타임아웃이 난무하고, 다 읽지도 못할(잘 알지도 못하는) 오픈소스 라이브러리들을 설치해야만 합니다.

다시 동시성으로 돌아가서 - 제가 사용가능한 스레드 개수에 제약을 받아본적이 있을까요?
아뇨 단한번도... 저는 코루틴도, 동시성 따위도 필요 없다고 생각합니다.
제 생각에 우리에게 필요한것은(우리 노력이 투자되어야 하는곳은) non-blocking 코드입니다.


Blocking code 이슈에 대해 (The issue with blocking code)

우리가 blocking 이라고 여기는 경우는 대부분 다음 둘중 하나이다.
정말 blocked 되었거나, 일이 완료되는데 수년 정도가 걸리는 경우이다.
인간이기때문에 우리는 참을성이 없다. 그런데 우리는 기계가 일을 끝내는데 특히 더 기다리기 힘들어 한다. 하지만 우리가 오랫동안 기다릴 것인지와 block 되는것을 피할 것인지에 대한 선택 역시 같은 문제에 봉착한다.
우리는 빨리 끝날 수 있는 일을 기다리기가 싫다. 뭔가 느린 DB 요청이 끝날때까지 기다리는 동안 다른 사용자에게는 그냥 빠른 응답을 해주고 싶다.
선점형 concurrency (= 스레드)는 매우 이러한 요구사항을 처리하기 좋은 방법이고, 몇가지 주요한 이점들이 있다.
- 코드 가독성이 좋다.
- 공유자원을 효과적으로 사용한다.
스레딩 방식의 가독성에 대해서는 - 딱히 말할것은 없지만, 읽기 쉽진 않지만 확실히 코루틴보다는 낫다.
자원과 관련해서는 - 상세 구현방식에 대해 조금 더 낫다가 아닌 훨씬 낫다고 말할 수 있다. 하지만 대부분은은 2개의 core 를 사용하거나 2 core 머신을 사용한다.
그래서 일반적인 threading 을 위해서 보통 우리는 요렇게 코드를 짠다.

def handle_user_request(request):
    thread_processing_data(request.data).start()
    return Response("OK", request)


그리고 만약 thread_processing_data 에서 타임아웃이 나면, 에러가 날것이다. 그리고 만일 가능하다면 두번째 core를 사용할 것이다. 꽤 괜찮다. 그리고 이것을 정확하게는 아니지만 비슷하게 파이썬으로 짤 수 있다. thread_processing_data 대신에 우리는 processing data 부분을 process로 감싼다.
물론 나는 그 좋은 multiprocessing library 에 대해 말하고 있는 것이다.
하지만 그게 정말로 더 좋을까?
난 여전히 몇가지 개념을 더 이해해야 하고, 그중 특히, 자원이 process 간에 어떻게 공유되는지 에 대해 확실히 알아야 한다.
더 좋은 방법이 있을까?


Lockless 의 승리 그리고 Celery (Lockless for the win and Celery)

내가 프로그래머로서 바라는 한가지가 있다면 block 이 되지않는 code 이다. 나는 그것이 프로세스를 활용하든, 스레드를 활용하든, transactional memory 든 어떤 마법이든 상관없다.

한 작업의 단위를 만들고 우선순위 등의 파라미터를 정하면 당신이 할 일은 끝이다. 그런 일을 할수 있게 해주는 파이썬 패키지가 하나 있으니 그게 바로 celery 다.
Celery는 하나의 프로젝트이며, 당신이 첫번째 Task를 돌리기전에 엄청나게 다양한 조합으로 써먹을수 있다. 그리고 task를 돌리기 시작하면, 정말 굉장하다.
예를들어 , 회사에서 다양한 SNS 데이터를 가져오는 system이 있다고 해보자. 지금처럼, API 콜은 시간이 걸리고, 당신은 네트웤 연결 후 데이터를 보내 리턴을 받아오기 까지의 시간을 표시해야만 한다고 해보자.

For example:

In [8]: %time update_metrics(e)
CPU times: user 1.2 s, sys: 137 ms, total: 1.34 s
Wall time: 1.35 s


음,,, 1초 이상걸리면 사용자향 코드에 사용할 수 없다. 하지만 난 이 코드를 최초 진입 화면에 들어갈 때애만 사용하고자 한다. 어떻게 할 수 있을까?
celery를 사용하면 난 그냥 update_metrics 함수를 task로 감싸 이렇게 만들수 있다.

update_metrics.apply_async((entry.id,), queue=settings.HIGH_PRIORITY_FRONTEND_QUEUE_KEY)

설명을 덧붙이자면:
update_metrics: cost 가 좀 있는 작업으로서, 이제 non-blocking 방식으로 실행된다.
queue: 여러 queue 중 어떤 것이 이 task를 handling 해야할지를 의미하는 parameter

update_metrics 는 처리되는데 장시간이 소요된다. - 하지만 Celery 덕에, 난 그것을 염려할 필요가 없게 되었다:
- 그것은 사용자 액션에의해 정확히 동작한다.
- 코드는 매우 가독성이 높고 직관적이다.
- 자원이 사용가능할때 사용된다.

그리고 무엇보다도 중요한것이: 코드가 I/O 를 하던말던, yield 를 써야 하는지 어쩐지, CPU 혹은 I/O 로 느려진것인지 아닌지 걱정할 필요가 전혀 없다.


Celery 의 능력 (Things Celery can do)

당신의 문제가 100개 URL을 긁어와서 사용자가 지정한 3개 단어의 출현빈도를 측정하는 것이라고 해보자.
일반적으로 이것은 몇가지 문제에 봉착한다 - 긁어온 URL들을 조합해야하고, connection은 timeout 이 날 수 있고, 작업이 끝날때까지 기다려야 하며, 게다가 어쩌면 사용자가 입력한 데이터를 저장해야 할수도 있다.
Celery 없이는 이런문제 해결이 정말 악몽같을 텐데, Celery를 쓰면 난 그냥 아래와 같은 Task 만 작성하면 땡이다:


import requests
from collections import Counter
from celery import task, chord, chain

@task(ignore_result=False)
def find_frequency(link_text, user_words):
    # we live the implementation as an exercise to the reader :)
    return {'foo': 1, 'bar': 1, 'baz': 1}

@task(ignore_result=False)
def scrape_url(url):
    response = requests.get(url)
    if response.status_code == 200:
        return response.text

@task(ignore_result=False)
def aggregate_results(results):
    counter = Counter()
    for result in results:
        counter.update(result)
    # do something with data
    return counter


user_submitted_words = ['foo', 'bar', 'john']
urls_to_scrape = []

async_result = chord(
    [chain(
        scrape_url.subtask(args=(url,)), 
        find_frequency.subtask(args=(user_submitted_words,)))
        for url in urls_to_scrape]
    )(aggregate_results.s())


이 코드예제의 알짜배기만 설명하면 이렇다:
- chain 은 tasks 들의 파이프라인을 만들수 있게 해주어 하나의 결과물이 다른 것으로 전달된다.
- chord 는 여러 task의 그룹을 만들어서 그 task 들이 모두 완료되었을때 특정한 하나의 task를 실행할 수 있도록 해준다.

여기서의 장점은 꽤 크다:
- 당신은 이것이 어떻게 실행될지 관심을 가질 필요가 없다. 그것은 스레드이거나 다중 process 이거나 coroutine 일 것이다.(Celery 어느정도 규모의 모든 종류 pool을 제공한다.)
- since you don't ??? (이라고 쓰여있는데... 갑자기 왜 쓰여있는지 모르겠음)

아아, 하지만 이 케이스에 또 꽤 큰 단점도 하나 있다:
- Celery task가 모두 함수여서, scrape_url.subtask(args=(url,)) 라는 그닥 가독성이 좋진 않은 문법을 써야만 한다.
- Celery는 task들의 import path를 깨끗히 해야하고, 각 task는 함수여야 한다. 주로 tasks.py 파일에 둔다. - 다른 task 안에 define(정의) 또는 submit(제출?) 작업을 할수 없다.
- 우리가 chained task 를 정의 하는것을 다른 어떤 task의 body 에 들어있는 task로 call할 수 없기 때문에, chord 나 chain 과 같은 코드를 복잡하게 하는 것들이 생겼다


잠글수 없는 성질 ? (Lockless?)

위에 나열한 문제 이외에, 나에게 가장 큰 문제는 결이 고운(=부드러운) 컨트롤이 부족하다는 것이다.
Queue는 lockless한 programming 모델을 얻기 위한 매우 원시적인 방법이다.

위 예제는 당신이 배치 작업들을 실행한뒤 이 결과를 모두 종합(aggregate)했다고 볼 수 있다. - 이게 맵리듀스로 짜면 한 30 라인정도 코드가 된다.
하지만 좀 더 어려운 디자인을 생각해보자. - 만일 concurrency 를 지원하지 않는 object 가 있다고 가정해보자. 완전히 lockless 하고 blocking 되지도 않는데 읽기도 해야하며 쓰기도 해야한다고 해보자.
어떻게 해야할까?

먼저 이렇게 할것이다 (난 여기서 당신이 Django integration 을 쓴다고 가정한다)

./manage.py celeryd -Q serial_queue -c 1

이게 하나의 worker 가 최대 한개의 task를 병렬로 돌리도록 하기위한 코드 전부이다


SERIAL_QUEUE_NAME = 'serial_queue'

@task()
def read_value():
    return get_lockless_api_value()

@task()
def increment_value():
    value = get_lockless_api_value()
    new_value = value + 1
    set_lockless_api_value(new_value)

result = read_value.apply_async(queue=SERIAL_QUEUE_NAME)
result = increment_value.apply_async(queue=SERIAL_QUEUE_NAME)
result = read_value.apply_async(queue=SERIAL_QUEUE_NAME)



그렇게 함으로써, 아무 특별한것도 없이 lock도 없이, GIL문제도 없이 우리는 값을 읽고 쓸 수 있게 된다. 물론, 한가지 주요 문제점이 있다. - 우리는 concurrent 한 읽기를 할수 없다 (가능해야 할지라도)


Final remarks (마지막으로 하고싶은 말)

나에게 있어, 이글은 GIL 과 couroutines/asyncio 에 대한 논쟁을 어느정도 요약했다고 본다. 내 생각에 우리가 파이썬 core 에 대해 가지고 있는 주요 문제는 그것이 C의 영향을 매우 많이 받았다는 것이다. 하지만 이것은 파이썬의 약점이다. 그리고 이 노력에 타당한 이유를 찾을 수 없다. (뭔 노력을 말하는건지...;;)

수백개의 회사들이 파이썬 코드를 중요 로직에 사용하고 있다 - 그리고 그것은 동기적인 single-threaded 코드이다. (Django가 얼마나 인기가 많은지 한번 찾아봐라) 어쩌면 몇십, 몇천의 사용자들을 그 회사들이 상대하고 있는데도 말이다.
내 생각에 만약 우리가 정말 제대로 된 concurrency를 파이썬으로 제공하고 싶다면, 이게(celery 말하는듯..) 그 방법이지 않을까 싶다. 프로그래머들이 직접 queue를 정의 하도록 한, 완전한 lockless paradigm에 queue를 사용한 원시적 방법을 소개 한다.

대부분의 것들은 이미 Celery로 구현되었다. 파이썬으로 그것을 사용하려면, 필요한 만큼의 worker와 queue 를 관리할수 있도록 python interpreter 를 확장 시키는것만 남았다. nested tasks 의 정의(definition)와 분배(dispatch)를 가능케 하기위해 약간의 syntax 용이성(=sugar)도 좀 가미하고 말이다.
그럼 꽤 쓸만해질 것이다.

내 생각에 우리는 프로그래머로서 concurrent 한 코드를 전혀 원한적이 없다.
그리고 정말 난 단언컨대, 코루틴이나 multiplex I/O 따위 필요 없었다.

내가 원하는건 내 아이디어를 내가 생각한대로 효과적으로 표현하기 위한 도구이다.
thread 나 concurrency 를 추상화해주면서...
그리고 lockless 한 패러다임이 그것을 해결할수 있도록 길러내(fostering)주면서...


1 2 3 4 5 6 7 8 9 10 다음


통계 위젯 (블랙)

2136
564
182774

GoogleAdsenseResponsive

Cluster map