Last active
March 1, 2024 17:20
-
-
Save fillest/a6bd2ba07ee5707e39041e05548a1ad2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
python3 -m venv venv | |
venv/bin/pip install -U pip | |
venv/bin/pip install -U setuptools wheel | |
venv/bin/pip freeze --all | grep -v pkg-resources | |
import argparse | |
cli_parser = argparse.ArgumentParser() | |
cli_parser.add_argument('--smth-str', default = 'val', help = "") | |
cli_parser.add_argument('-n', type = int, default = 2, choices = [1, 2, 3]) | |
cli_parser.add_argument('-o', '--optional-smth', action = 'store_true') | |
cli_parser.add_argument('smth-required') | |
cli_args = cli_parser.parse_args() | |
import sys | |
print("...", file=sys.stderr) #print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False) | |
import sys; print ...; sys.stdout.flush() #py2 | |
import logging | |
logging.basicConfig(level = logging.INFO, format = '%(asctime)s %(levelname)-5.5s %(name)s:%(lineno)d:%(funcName)s %(message)s') | |
logger = logging.getLogger(__name__) | |
logger.error("%s %s", 1, 2) #debug, info, warning, critical, exception | |
"%.3f" % 0.5556 #0.556 | |
f"{elapsed:0.2f} sec" | |
"{a:.3f}".format(a = 0.5556) #"{:.3f}".format(0.5556) | |
# %d for ints | |
"%-4s" % #pad right with spaces | |
"%+4s" % #pad left with spaces | |
#shallow-merge dicts | |
a | b #v3.9+ | |
{**a, **b} #v3.5+ | |
{**a, 'k': 123} | |
#note: can throw OSError: [Errno 18] Invalid cross-device link | |
import tempfile | |
import os | |
def write_file (fpath, content): | |
fd, tmp_fpath = tempfile.mkstemp() | |
try: | |
with open(tmp_fpath, 'wb') as f: | |
f.write(content) | |
finally: | |
os.close(fd) | |
os.rename(tmp_fpath, fpath) | |
def main (): | |
# | |
if __name__ == '__main__': | |
main() | |
import datetime | |
datetime.datetime.utcfromtimestamp(ts) | |
datetime.datetime.utcnow() | |
datetime.timedelta(hours = 3) | |
dt.strftime('%Y.%m.%d %H:%M:%S') | |
datetime.datetime.strptime(s, '%Y-%m-%d %H:%M:%S') | |
calendar.timegm(dt.utctimetuple()) #import calendar | |
#modern py3 https://blog.miguelgrinberg.com/post/it-s-time-for-a-change-datetime-utcnow-is-now-deprecated | |
now = datetime.datetime.now(datetime.timezone.utc) | |
#modern py3 | |
import datetime | |
import time | |
def datetime_parse_utc(s: str, format: str): | |
return datetime.datetime(*(time.strptime(s, format)[:6]), tzinfo=datetime.timezone.utc) | |
datetime_parse_utc('2024-03-01 15:23:32', '%Y-%m-%d %H:%M:%S') | |
import signal | |
import sys | |
should_stop = [False] | |
def plan_stop (signum, _frame): | |
if signum == signal.SIGTERM: | |
should_stop[0] = True | |
print("caught SIGTERM", file = sys.stderr) | |
else: | |
print(f"caught unexpected signal {signum}", file = sys.stderr) | |
def main (): | |
signal.signal(signal.SIGTERM, plan_stop) | |
_got_signal = False #good enough to consider atomic | |
def _handle_signal (signum, _frame): | |
global _got_signal | |
_got_signal = True | |
print(f"Got signal: {signal.Signals(signum).name}", file = sys.stderr, flush = True) | |
def init_stop_signal_handlers (signals = {signal.SIGTERM, signal.SIGINT}): | |
for sig in signals: | |
signal.signal(sig, _handle_signal) | |
def got_stop_signals (): | |
global _got_signal | |
return _got_signal | |
import contextlib | |
import cStringIO | |
import gzip | |
def compress (str_): | |
with contextlib.closing(cStringIO.StringIO()) as buf: | |
buf.seek(0) | |
buf.truncate(0) | |
with gzip.GzipFile(fileobj = buf, compresslevel = 8, mode = 'wb') as gzf: | |
gzf.write(str_) | |
return buf.getvalue() | |
def decompress (bindata): | |
with contextlib.closing(cStringIO.StringIO(bindata)) as strfile: | |
with gzip.GzipFile(fileobj = strfile, mode = 'rb') as gzfile: | |
return gzfile.read() | |
#jinja2 | |
{{ var|default('not defined') }} | |
{% if somevar is defined %} | |
{% endif %} | |
#library logging, to prevent "No handlers could be found for logger ...". in __init__.py | |
logging.getLogger(__name__).addHandler(logging.NullHandler()) | |
#build url | |
'...?' + urllib.urlencode({'id': 1}) | |
import requests | |
from requests.auth import HTTPBasicAuth | |
with requests.Session() as sess: | |
sess.auth = HTTPBasicAuth(os.getenv('user', 'test'), os.getenv('password', 'test')) | |
timeout = (10, 30) #not avail for session | |
resp = sess.post('https://url', params = {'name': 123}, data = {'name': 123}, timeout = timeout) | |
#jinja2 | |
# {# comment #} | |
# ... ## comment --TODO check if enabled by default | |
import threading | |
#py2 | |
thr = threading.Thread(target = fn, name = 'myname', args = [], kwargs = {}) | |
thr.daemon = True | |
#py3 | |
thr = threading.Thread(target = fn, name = 'myname', args = [], kwargs = {}, daemon = True) | |
thr.start() | |
thr.join() | |
lock = threading.Lock() | |
with lock: | |
# | |
import concurrent.futures | |
with concurrent.futures.ThreadPoolExecutor(max_workers = 2) as executor: | |
futures = [ | |
executor.submit(fn), | |
executor.submit(fn), | |
] | |
#shutdown (with) waits by default - no need to call anything if you don't need result or to raise | |
for future in concurrent.futures.as_completed(futures): | |
ret = future.result() #raises | |
#by default suppresses exceptions - e.g. wrap the callback | |
#use cancel_futures to stop (e.g. on signal) or check at start of the callback | |
#decorator | |
import functools | |
def final_name (_arg): | |
def deco (orig_fn): | |
@functools.wraps(orig_fn) | |
def wrapper (*args, **kwargs): | |
return orig_fn(*args, **kwargs) | |
return wrapper | |
return deco | |
#py3 json to/from file | |
with open(fpath, 'w', encoding = 'utf-8') as f: | |
json.dump(v, f, ensure_ascii = False) | |
with open(fpath, encoding = 'utf-8') as f: | |
v = json.load(f) | |
import sys; assert sys.version_info[0] > 2, "python3 required" | |
from operator import itemgetter | |
alist.sort(key = itemgetter(0)) | |
https://mypy.readthedocs.io/en/stable/cheat_sheet_py3.html#built-in-types | |
#fabric stuff | |
with hide('stdout'): | |
out = run('') | |
#regexps | |
import re | |
match = re.match(r'^foo(.+)$', s) | |
if match: | |
match[1] #--py3? | |
re.search(r'^foo(.+)$', s, re.MULTILINE) | |
#combining string literal modifiers | |
a = 1; print(rf'\\ {a}') | |
> \\ 1 | |
#kw-only | |
def fn (*, arg): pass | |
fn(arg = 123) | |
os.path.expanduser('~/some-path') | |
class N: | |
def __init__(self): | |
self.v = 1 | |
random.randint(1, 3) #1 to 3 inclusively | |
import contextlib | |
@contextlib.contextmanager | |
def fn (...): | |
res = ... | |
try: | |
yield res | |
finally: | |
... |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment