Install pip
If you end up on a system without pip, you can install it from a script.
wget https://bootstrap.pypa.io/get-pip.py # Download installation script
python3 get-pip.py # Run installation script
Read file line-by-line and print each line
def print_lines(file):
with open(file) as f:
for line in f:
print(line)
Read file into list
def return_list(file):
with open(file) as f:
list = f.readlines()
return list
Remove line from a file containing a specified string
def remove_line_containing_string(file):
f = open(file, 'r')
contents = f.readlines()
f.close()
f = open(file, 'w')
for line in contents:
if not 'some string' in line:
f.write(line)
f.close()
Check if file exists
def file_exists(file):
if os.path.isfile(file):
return True
else:
return False
Find and replace line in a file
def find_and_replace_in_file(inp_file, old, new):
new_output = ''
with open(inp_file, 'U') as f:
new_output = f.read()
while old in new_output:
new_output = new_output.replace(old, new)
with open(inp_file, 'w') as f:
f.write(new_output)
Resource: https://bhagat.blog/2017/01/06/replacing-string-in-a-file-using-python/
Run command and get output
This can be found as part of mypyutils
import subprocess
def run_cmd(cmd):
p = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE)x
output, err = p.communicate()
return output.decode().strip()
# Example:
print(run_cmd("uname -a"))
Python3 Simple HTTP Server
python3 -m http.server <port>
IPv6 server
web_server.py
:
from http.server import HTTPServer, SimpleHTTPRequestHandler
import socket
class HTTPServerV6(HTTPServer):
address_family = socket.AF_INET6
server = HTTPServerV6(('::', 8080), SimpleHTTPRequestHandler)
server.serve_forever()
Resource: https://stackoverflow.com/questions/25817848/python-3-does-http-server-support-ipv6
Python2 Simple HTTP Server
python -m SimpleHTTPServer <port>
Get password as input
import getpass
try:
password = getpass.getpass()
except Exception as error:
print('ERROR', error)
Resource: https://www.geeksforgeeks.org/getpass-and-getuser-in-python-password-without-echo/
Regex
Group matching
>>> import re
>>> m = re.match(r"(\w+) (\w+)", "Isaac Newton, physicist")
>>> m.group(0)
'Isaac Newton'
>>> m.group(1)
'Isaac'
>>> m.group(2)
'Newton'
>>> m.group(1,2)
('Isaac', 'Newton')
Resource: https://docs.python.org/2/library/re.html
Regex testers
Regex to match a line in a file
# input could be something like:
# dog 2
pattern = re.compile("\w+(\d+)")
with open(file) as f:
for line in f:
m = pattern.match(line)
if m:
print(f"Found this item: {m.group(1)}")
List operations
Reverse list
>>> l = [1,2,3,4]
>>> rl = l[::-1]
>>> rl
[4, 3, 2, 1]
Resource: https://stackoverflow.com/questions/47025356/reverse-index-in-a-list
Count elements in a list
len(list)
Resource: https://stackoverflow.com/questions/4130027/python-count-elements-in-list
String to list
string.split()
Resource: https://stackoverflow.com/questions/8266529/python-convert-string-to-list
List to comma-separated string
a_list = ["a", "b", "c"]
joined_string = ",".join(a_list)
Resource: https://www.kite.com/python/answers/how-to-make-a-list-into-a-comma-separated-string-in-python
Check if list is empty
if not a:
print("List is empty")
Resource: https://stackoverflow.com/questions/53513/how-do-i-check-if-a-list-is-empty
Get first two characters of a string
<string var>[2:]
Resource: https://stackoverflow.com/questions/1270990/how-to-remove-two-chars-from-the-beginning-of-a-line
File operations
List only files in a directory
from os import listdir
from os.path import isfile, join
onlyfiles = [f for f in listdir(mypath) if isfile(join(mypath, f))]
Remove file
os.remove('path/to/file')
Change directory
os.chdir('/etc/')
Remove directory if it exists
if os.path.isdir(self.repo_name):
shutil.rmtree(self.repo_name)
Remove all jpg files from current folder (python 2)
import glob, os
for f in glob.glob("*.jpg"):
os.remove(f)
Remove all jpg files from current folder (python 3)
from pathlib import Path
for p in Path(".").glob("*.jpg"):
p.unlink()
Run command
os.system('ls')
Break up long command
from mypyutils import sysutils
output = sysutils.run_cmd('aws ec2 describe-images --filters \
"Name=name,Values=Kali-X2Go" --output json')
List comprehension
This for loop:
for x in range(int(sp),int(ep)+1):
port_scan(site,int(x))
can also be represented as this list comprehension:
[port_scan(site, int(x)) for x in range(int(sp), int(ep)+1)]
Dictionary comprehension
Similar concept to a list comprehension.
This will create a dictionary that maps an idea to the number of times someone has had it if the idea is greater than 4 characters:
all_my_ideas = {idea:ideas.count(idea) for idea in ideas if len(idea) > 4}
Resource: https://stackoverflow.com/questions/3496518/using-a-dictionary-to-count-the-items-in-a-list
Print a line from a list
print(list[0])
String interpolation with Python 3.6.x
import os
site = 'https://google.com'
os.system(f"open -a /Applications/Google\ Chrome.app {site}")
Escape fstring
In the event you need to have a ‘{’ in your string, use ‘{{’ to escape it
>>> foo = 'test'
>>> f'{foo} {{bar}}'
'test {bar}'
Resource: https://stackoverflow.com/questions/42521230/how-to-escape-f-strings-in-python-3-6
String interpolation with older Python
import os
site = 'https://google.com'
os.system("open -a /Applications/Google\ Chrome.app %s" % site)
The newer way with older Python
with open(file) as f:
for line in f:
print(run_cmd("nmap --open -Pn -top-ports 1000 -T4 -sS -g80 -sC -sV {target}".format(target=line)))
Resource: https://realpython.com/python-string-formatting/
Multiline list
list = [
'item1',
'item2',
]
Create requirements.txt with pip
pip freeze > requirements.txt
Debug one-liner
import pdb; pdb.set_trace()
Show global vars in pdb
globals()
Loop in pdb
If you want to be able to test an if
statement (for example) in pdb, you’ll need
to run this first:
!import code; code.interact(local=vars())
Code Introspection
The ability to examine classes, functions and keywords to get a better sense for what they do.
Show available methods for an object
dir(object)
Show object type
type(object)
Resource: https://jobtensor.com/Tutorial/Python/en/Code-Introspection
Remove \n and extra quotes from an object
obj.rstrip().replace('"', '')
Remove newlines and carriage returns
'blablabla\r\n'.strip()
Check if current user is root, exit if not
def check_root():
if not os.geteuid() == 0:
sys.exit('This script must be run as root!')
Run remote command using ssh on an aws instance
import paramiko
k = paramiko.RSAKey.from_private_key_file("/path/to/pem/file")
c = paramiko.SSHClient()
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
c.connect( hostname = "<ec2 hostname>", username = "<username>", pkey = k )
stdin , stdout, stderr = c.exec_command("<command to run>")
print("stdout: " + stdout.read().decode('utf-8'))
print("stderr" + stderr.read().decode('utf-8'))
c.close()
Resource: http://diego-pacheco.blogspot.com/2016/05/having-fun-with-boto-3.html
Auto enable virtualenv for a directory
Use https://github.com/kennethreitz/autoenv, which can be installed via brew, pip, etc.
Once it’s installed, add this line to your bash_rc or zshrc or whatever (the path
will vary based on which installation method you used):
source /usr/local/opt/autoenv/activate.sh
Once this is done, you simply drop a .env file into the directory which has a virtualenv,
that should look like this:
source .venv/bin/activate
Now whenever you cd into this directory, virtualenv will automatically be activated.
You will have to deactivate
manually when you leave though.
Standards
This is a great guide for writing python code in general.
The Google guide is also quite helpful.
Commenting
A nice example can be found here for google style.
Pipenv
Install pipenv
pip3 install -U pipenv
Resource: https://github.com/pypa/pipenv/issues/1781
Set up pipenv for a project with python version 3.6.5
pipenv --python 3.6.5
Install a dependency
pipenv install <package>
Lock the dependencies
You want to do this before a release:
pipenv lock
Run a command from the virtualenv for a project
pipenv run python -V
pipenv run python -c 'print("A" * 32)'
Activate the virtualenv
pipenv shell
Deactivate the virtualenv
CTRL-d
or type exit
Remove the virtualenv
pipenv --rm
Import from requirements.txt
pipenv install -r requirements.txt
Resources:
- https://pipenv-fork.readthedocs.io/en/latest/basics.html
- https://github.com/pypa/pipenv
- https://github.com/pypa/pipenv/issues/84
- https://robots.thoughtbot.com/how-to-manage-your-python-projects-with-pipenv
Pyenv
Install pyenv on macOS
brew install pyenv
echo 'PATH=$(pyenv root)/shims:$PATH' >> ~/.zshrc
Install version of python
PY_VER=3.8.12
pyenv install "${PY_VER}"
Set version of python for a directory
PY_VER=3.8.12
pyenv local "${PY_VER}"
Show versions of python on the system
pyenv versions
Set global python version
PY_VER=3.8.12
pyenv global "${PY_VER}"
Resource: https://opensource.com/article/20/4/pyenv
List licenses of dependencies
pip install pip-licenses
Get first occurrence of a char in a string
The index()
function gets the index of the first occurrence of a char starting
from the beginning of a string and returns it.
The rindex()
function gets the index of the first occurrence of a char starting
from the end of a string and returns it.
>>> s = "dedjdedl"
>>> s.index('d')
0
>>> s.rindex('d')
6
Combine two lists with zip
>>> l1 = ['a','b','c']
>>> l2 = [1,2,3]
>>> print(list(zip(l1,l2)))
[('a', 1), ('b', 2), ('c', 3)]
Combine two lists together and iterate over them
combined = zip(list1, list2)
for list1, list2 in combined:
print(list1)
Print the columns of a matrix
>>> a = [[1,2],[3,4],[5,6]]
>>> print(list(zip(*a)))
[(1, 3, 5), (2, 4, 6)]
Data types and examples
set
Store unordered collections of unique elements
>>> items = [1,5,2,2,3,5,1]
>>> set(items)
{1, 2, 3, 5}
Iterate through list with idx and value
for idx, val in enumerate(list_of_stuff):
print(idx)
print(val)
Iterate through range with an incrementor of 100
for i in range(start, end, 100):
Resource: https://stackoverflow.com/questions/4930404/how-do-get-more-control-over-loop-increments-in-python
Random number in a range
import random
print(random.randint(1,101))
Search and replace text inline in a file
with fileinput.FileInput("file.txt", inplace=True) as file:
for line in file:
print(line.replace('stringtoreplace', 'replacementstring'), end='')
https://stackoverflow.com/questions/17140886/how-to-search-and-replace-text-in-a-file-using-python
Generate random id w/ lowercase letters and numbers
def id_generator(size=20, chars=string.ascii_lowercase + string.digits):
return ''.join(random.choice(chars) for _ in range(size))
Open new tab and run ls with above run_cmd()
run_cmd(f"gnome-terminal --tab --active -- bash -c 'ls ; exec bash'")
Break up long string
print('This is a really long string' \
'and it should be broken up')
Run simple http webserver from code
web_lport = 8000
def start_webserver():
url = f"localhost:{web_lport}"
handler = http.server.SimpleHTTPRequestHandler
httpd = socketserver.TCPServer(("", web_lport), handler)
print(f"Web server starting on port {web_lport}")
server_process = multiprocessing.Process(target=httpd.serve_forever)
server_process.daemon = True
server_process.start()
return server_process
server_process = start_webserver()
# Do stuff
print(f"Closing web server running on port {web_lport}")
server_process.terminate()
Run SimpleHTTPServer as a background job
if [[ "$(pgrep tmux)" ]]; then
kill -9 `top -n 1 | pgrep tmux`
fi
tmux new -s web_server -d 'python -m SimpleHTTPServer'
sleep 1
python do_things.py
Resources: https://superuser.com/questions/927544/run-command-in-detached-tmux-session-and-log-console-output-to-file https://gist.github.com/pwittchen/531c0bed8a20c1f06231
Append to file
with open("test.txt", "a") as myfile:
myfile.write("appended text")
Resource: https://stackoverflow.com/questions/4706499/how-do-you-append-to-a-file-in-python
Multi-line string
s = """ this is a very
long string if I had the
energy to type more and more ..."""
Resource: https://stackoverflow.com/questions/10660435/pythonic-way-to-create-a-long-multi-line-string
Requests
Include hex chars
A hex character can be included by doing the following (observe the \x09
):
headers = {
'Host': host+':'+port,
'Content-Length': '85',
'Transfer\x09-Encoding': 'chunked',
}
Another example:
data = '0\x0d\x0a\x0d\x0a' \
'GET /' \
'/ HTTP/1.1\x0d\x0aHost: ' + host + ':' + port'
Override the content-length
This is done by using a prepared request. In this example, the content-length will be set to 85, no matter what:
s = requests.Session()
req = requests.Request("POST", protocol+'://'+host+':'+port,
headers=headers, data=data)
prepped = req.prepare()
prepped.headers['Content-Length'] = 85
s.send(prepped)
Intercept request with a proxy
This is useful for intercepting requests coming from a piece of malware that’s python-based.
proxies = {"http": "http://127.0.0.1:8090", "https": "http://127.0.0.1:8090"}
response = requests.post(target_url, headers=headers, json=data, verify=False, timeout=15,
proxies=proxies)
Resource: https://www.th3r3p0.com/random/python-requests-and-burp-suite.html
Run a command from the command line
python -c 'print "A" * 32'
Copy output using pbcopy
in OSX:
python -c "print('b'*64)" | pbcopy
Dictionary Notes
Add value to list in dictionary if it doesn’t exist; otherwise append the value to the existing list.
if not dict.has_key(key):
dict[key] = [value]
else:
dict[key].append(value)
Create empty dict
dict = {}
Assign incrementor to key
In this instance, we’ll say that c
is a random character, and we’re currently counting
the number of instances of this character in a string.
dict[c] = 1
Increment incrementor
dict[c] += 1
Print a dictionary to a table
Just use https://pypi.python.org/pypi/PrettyTable and save yourself a headache.
from prettytable import PrettyTable
def output_dict_to_table(in_dict):
"""
Print an input dictionary as a table
Usage:
output_dict_to_table({'Key': ['Value'], 'Key2': ['Value2', 'Value3']})
"""
t = PrettyTable(['Key', 'Value'])
for k, v in in_dict.items():
t.add_row([k, v])
print t
JSON from output of running a program to dict
This example uses the run_cmd function above.
# Output is bytes; convert to string with the .decode('utf-8')
output = run_cmd('terraform output -json').decode('utf-8')
tf_json = json.loads(output)
The tf_json
object will be properly set up as a python dictionary.
Resources:
- https://stackoverflow.com/questions/606191/convert-bytes-to-a-string
- https://realpython.com/python-json/
List of chars or string to dict with counter
This dictionary will have counters for each letter. If there are duplicate letters, the counter will increment, i.e.
['h','e','l','l','o']
will return the following:
{'l': 2, 'h': 1, 'e': 1, 'o': 1}
The code to do this is as follows:
from collections import Counter
print(Counter(['h','e','l','l','o']))
Note that you can also use this with a string, i.e.
from collections import Counter
print(Counter('hello'))
Dictionary that has a dictionary as its value
This particular example will output a dictionary that has a word as its key and a dictionary as the value that maps each letter of the word to the number of times it appears.
from collections import Counter
words = ['hi', 'bye', 'toodles']
word_to_chars = {}
for word in words:
word_to_chars[word] = Counter(word)
print(word_to_chars)
# {'bye': Counter({'y': 1, 'b': 1, 'e': 1}), 'hi': Counter({'i': 1, 'h': 1}), 'toodles':
Counter({'o': 2, 'e': 1, 'd': 1, 'l': 1, 's': 1, 't': 1})}
Check if value in a list of dictionaries
def check_if_in_list_of_dict(sample_dict, value):
"""Check if given value exists in list of dictionaries """
for elem in sample_dict:
if value in elem.values():
return True
return False
if check_if_in_list_of_dict(dict_name, 'value'):
print('yep')
Resource: https://thispointer.com/python-check-if-value-exists-in-list-of-dictionaries/
Selenium
Open new tab
# Open new tab
driver.execute_script("window.open('');")
# Switch to new tab
driver.switch_to.window(driver.window_handles[1])
# Load stackoverflow
driver.get("http://stackoverflow.com")
# Wait for page to load
time.sleep(3)
# Close the new tab
driver.close()
Switch back to the first tab
driver.switch_to.window(driver.window_handles[0])
Resource: https://stackoverflow.com/questions/28431765/open-web-in-new-tab-selenium-python
Get page source
driver.page_source
Resource: https://pythonbasics.org/selenium-get-html/
Get all cookies
driver.get_cookies()
Get a particular cookie’s value
driver.get_cookie('cookie_name')['value']
Integrate with browsermob and Chrome
In the event you need to be able to get request and/or response data, you’ll probably want to look at using a proxy like browsermob.
A fully working example can be found here.
Integrate with browsermob and Firefox
from selenium import webdriver
from browsermobproxy import Server
import time
server = Server(
path="./assets/browsermob-proxy-2.1.4/bin/browsermob-proxy", options={'port':
8095})
server.start()
proxy = server.create_proxy()
profile = webdriver.FirefoxProfile()
selenium_proxy = proxy.selenium_proxy()
profile.set_proxy(selenium_proxy)
driver = webdriver.Firefox(firefox_profile=profile)
proxy.new_har('req', options={'captureHeaders': True, 'captureContent': True})
driver.get("https://www.google.com")
print(proxy.har)
server.stop()
driver.quit()
Resources:
- https://www.youtube.com/watch?v=r0ne6zrqVaQ
- https://stackoverflow.com/questions/50550496/browsermob-proxy-python-how-to-get-response-body
- https://github.com/AutomatedTester/browsermob-proxy-py
- https://stackoverflow.com/questions/48201944/how-to-use-browsermob-with-python-selenium/48387421#48387421
- http://quabr.com:8182/58954036/chrome-browser-certificate-is-not-trusted-issue-using-browsermob-proxy
Click XPath Element
Using Chrome, I do the following to get the information I need to trigger an event-driven dropdown and then click one of the listed items:
- Get to the point where the menu is presented, stop with pdb
- Right click the element we want to click, Inspect
- Right click that element, click Copy and then Copy XPath
- Trigger the click event with selenium:
driver.find_element_by_xpath('<copied xpath>').click()
Continue on in this manner until you have the desired behavior.
Parse table from page
import pandas as pd
table = pd.read_html(driver.page_source)
# Print all values associated with a particular column
df = table
print(df.<column_name>)
# for example:
# print(df.IP)
Resources: https://beenje.github.io/blog/posts/parsing-html-tables-in-python-with-pandas/ https://stackoverflow.com/questions/6325216/parse-html-table-to-python-list
Click element based on text
This is one option:
driver.find_element_by_xpath(
"//*[contains(text(), 'text to match')]")
This is another (specifically for a button):
driver.find_element_by_xpath(
"//button[normalize-space()='text to match']").click()
Resources: https://www.guru99.com/using-contains-sbiling-ancestor-to-find-element-in-selenium.html https://stackoverflow.com/questions/12323403/how-do-i-find-an-element-that-contains-specific-text-in-selenium-webdriver-pyth https://stackoverflow.com/questions/49906237/how-to-find-button-with-selenium-by-its-text-inside-python
Send Backspace to an element
from selenium.webdriver.common.keys import Keys
driver.find_element_by_name('elementName').send_keys(Keys.BACK_SPACE)
Wait for element in page to load
from selenium.webdriver.support import expected_conditions as EC
# wait for 10 seconds for the page to load
delay = 10
try:
WebDriverWait(driver, delay).until(
EC.presence_of_element_located((By.ID, 'name of id associated with element
you want')))
except TimeoutException:
sys.exit("Loading the page took too much time, exiting!")
Argparse
Argparse is great for when you need to use CLI arguments - it’s clean and can be implemented with minimal fuss.
import argparse
def parse_arg():
parser = argparse.ArgumentParser(description='Do stuff')
parser.add_argument("-a", '--argument', required=True, help='description of what
your awesome code does')
return parser.parse_args()
# Return value of a single argument if you don't have multiple ones:
#return parser.parse_args().arg
For an example of how I’ve used this previously, check this page out: https://github.com/l50/base64_rot13_decoder
Mutually exclusive options
import argparse
def __parse_args__():
parser = argparse.ArgumentParser(
description='Do stuff.')
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument('-f', action=.....)
group.add_argument('-d', type=bool, help='do a boolean thing')
return parser.parse_args()
Resource: https://stackoverflow.com/questions/11154946/require-either-of-two-arguments-using-argparse
Add a debug mode
If you want to have a flag that defaults to true (so you don’t have to specify it as an argument), do the following:
parser.add_argument('-d', dest="debug", action='store_true',
help='debug mode')
Resource: https://docs.python.org/3/library/argparse.html
Check if port is open
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
result = sock.connect_ex(('127.0.0.1',80))
if result == 0:
print "Port is open"
else:
print "Port is not open"
sock.close()
Resource: https://stackoverflow.com/questions/19196105/how-to-check-if-a-network-port-is-open-on-linux
Show output as command runs
status_code = subprocess.call(
['ansible-playbook', 'site.yml', '-i', 'hosts'])
# status_code = 0 is an indicator of running the command successfully
Resource: https://www.cyberciti.biz/faq/python-run-external-command-and-get-output/
Send email to multiple recipients
import smtplib
from email.mime.text import MIMEText
smtp_user = 'youruser@yourdomain.com'
smtp_pw = 'YEP PUT THAT HERE'
sender = ['yoursender@domain.com']
recipients = ['person1@gmail.com', 'person2@gmail.com']
msg = MIMEText('Sweet text br0')
msg['Subject'] = "Awesome Subject
msg['From'] = ','.join(sender)
msg['To'] = ','.join(recipients)
s = smtplib.SMTP('smtp.mailgun.org', 587)
s.login(smtp_user, smtp_pw)
s.sendmail(sender, recipients, msg.as_string())
s.quit()
Send email with CC
import smtplib
from email.mime.text import MIMEText
smtp_user = 'youruser@yourdomain.com'
smtp_pw = 'YEP PUT THAT HERE'
sender = ['yoursender@domain.com']
recipient = ['person1@gmail.com']
cc_emails = ['person2@gmail.com', 'person3@gmail.com']
msg = MIMEText('Sweet text br0')
msg['Subject'] = "Awesome Subject
msg['From'] = ','.join(sender)
msg['To'] = ','.join(recipient)
msg['Cc'] = ','.join(cc_emails)
s = smtplib.SMTP('smtp.mailgun.org', 587)
s.login(smtp_user, smtp_pw)
s.sendmail(sender, recipient+cc_emails, msg.as_string())
s.quit()
Resources: https://stackoverflow.com/questions/49062924/send-e-mail-to-multiple-cc-and-multiple-to-recipients-simultaneously-using-pytho https://stackoverflow.com/questions/1546367/python-how-to-send-mail-with-to-cc-and-bcc
Git
Clone
git.Repo.clone_from(f"https://github.com/{self.user_name}/{self.repo_name}.git",
f"./{self.repo_name}")
Add/commit/push via http git
os.environ['GIT_USERNAME'] = config.username
os.environ['GIT_PASSWORD'] = config.passwordrepo_path = 'repo_name'
try:
repo = git.Repo(repo_path)
repo.git.add(update=True)
repo.index.commit('Commit Message')
origin = repo.remote(name='origin')
origin.push()
print("Pushed the latest commit to the repo!")
except Exception as e:
print(f"Failed to push the new commit due to {e}")
os.unsetenv('GIT_USERNAME')
os.unsetenv('GIT_PASSWORD')
Resources:
- https://stackoverflow.com/questions/44784828/gitpython-git-authentication-using-user-and-password
- https://stackoverflow.com/questions/41947096/git-push-using-python/41950141
- https://stackoverflow.com/questions/18178038/how-to-clear-os-environ-value-for-only-one-variable-in-python/18178048
Generate hashed password w/ salt
from typing import Dict
import binascii
import hashlib
import hmac
import secrets
import string
import uuid
def gen_pw(size: str) -> str:
return ''.join((secrets.choice(string.ascii_letters + string.digits + string.punctuation)
for i in range(size)))
def create_pw_hash(size: int) -> Dict[bytes, bytes]:
"""
Hash the provided password with a randomly-generated salt and return the
salt and hash to store in the database.
"""
salt = secrets.token_bytes(32).hex().upper()
password = gen_pw(size)
key = hashlib.sha256(password.encode('utf-8') + salt.encode('utf-8'))
return { 'salt': salt, 'key': key.hexdigest(), 'pw': password }
def is_correct_password(salt: str, pw_hash: str, password: str) -> bool:
"""
Given a previously-stored salt and hash, and a password provided by a user
trying to log in, check whether the password is correct.
"""
return hmac.compare_digest(
pw_hash,
hashlib.sha256(password.encode('utf-8') + salt.encode('utf-8')).hexdigest()
)
output = create_pw_hash(32)
assert(is_correct_password(output['salt'], output['key'], output['pw']))
Resources:
- https://docs.python.org/3.5/library/hashlib.html
- https://nitratine.net/blog/post/how-to-hash-passwords-in-python/
- https://pynative.com/python-generate-random-string/#h-generate-a-secure-random-string-and-password
- https://stackoverflow.com/questions/9594125/salt-and-hash-a-password-in-python
- https://nitratine.net/blog/post/how-to-hash-passwords-in-python/
- https://github.com/rsp2k/guacamole-import/blob/02899cac9419124302b7de8057c9311126a22f21/import-user-mapping.py#L180
Get words from a web page into a list
strings_from_html = ' '.join(BeautifulSoup(html_code, "html.parser").stripped_strings)
words = strings_from_html.split()
Resource: https://stackoverflow.com/questions/328356/extracting-text-from-html-file-using-python
Get top three most common strings in a dictionary
from collections import Counter
stuff = {'bla':4,'hey':6,'chicken':2,'bob':10}
counter = Counter(stuff)
print(counter.most_common(3))
Resource: https://www.geeksforgeeks.org/python-program-to-find-the-highest-3-values-in-a-dictionary/
String to byte string
# Random string
a = '6f8FGlE(u'
str.encode(a)
Byte string to string
# Random string
a = b'6f8FGlE(u'
a.decode('utf-8')
Resource: https://stackoverflow.com/questions/606191/convert-bytes-to-a-string
Hex string to byte string
hex_string = '6465616462656566'
bytes.fromhex(hex_string)
# b'deadbeef'
Byte string to hex
byte_string = b"deadbeef"
byte_string.hex()
# '6465616462656566'
Resource: https://stackoverflow.com/questions/5649407/hexadecimal-string-to-byte-array-in-python
Get hrefs in a site
from bs4 import BeautifulSoup
soup = BeautifulSoup(input, 'html.parser')
for a in soup.find_all('a', href=True):
if a.text:
print(a['href'])
Get home dir
Python 3.5+:
from pathlib import Path
home = str(Path.home())
Alternative:
from os.path import expanduser
home = expanduser("~")
Resource: https://stackoverflow.com/questions/4028904/how-to-get-the-home-directory-in-python
Simple CLI
import argparse
# Initialize parser
parser = argparse.ArgumentParser()
# Adding optional argument
parser.add_argument('--foo', type=str, help='foo help')
# Read arguments from command line
args = parser.parse_args()
Reference your input in your code with:
print(args.foo)
Resources:
- https://docs.python.org/3/library/argparse.html - official docs
- https://www.geeksforgeeks.org/command-line-arguments-in-python/ - provided explanation for how everything works
Get path of home directory
import os
print(os.path.expanduser('~')
Resource: https://www.kite.com/python/examples/4284/os-get-the-path-of-the-home-directory
Copy file
import shutil
# Source path
source = "/home/User/Documents/file.txt"
# Destination path
destination = "/home/User/Documents"
try:
shutil.copyfile(source, destination)
print("File copied successfully.")
# If source and destination are same
except shutil.SameFileError:
print("Source and destination represents the same file.")
# If destination is a directory.
except IsADirectoryError:
print("Destination is a directory.")
# If there is any permission issue
except PermissionError:
print("Permission denied.")
# For other errors
except:
print("Error occurred while copying file.")
Resource: https://www.geeksforgeeks.org/python-shutil-copyfile-method/
Change CWD without absolute path
import os
abspath = os.path.abspath(__file__)
dname = os.path.dirname(abspath)
os.chdir(dname)
Create file and any parent directories
This will do the same thing as mkdir -p
:
import os, os.path
def safe_open_w(path):
''' Open "path" for writing, creating any parent directories as needed.
'''
os.makedirs(os.path.dirname(path), exist_ok=True)
return open(path, 'w')
with safe_open_w('/Users/bill/output/output-text.txt') as f:
f.write(...)
Resource: https://stackoverflow.com/questions/23793987/write-file-to-a-directory-that-doesnt-exist
Create a salted password hash for /etc/shadow
Run the following to generate the hash on your linux machine:
python3 -c 'import crypt; print(crypt.crypt("sickpasswordbro!", crypt.mksalt(crypt.METHOD_SHA512)))'
Resource: https://serverfault.com/questions/330069/how-to-create-an-sha-512-hashed-password-for-shadow