Differences
This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision | |||
| knowledge_base:programming:python:python3 [2024/12/26 23:12] – removed - external edit (Unknown date) 127.0.0.1 | knowledge_base:programming:python:python3 [2024/12/26 23:12] (current) – ↷ Page moved from knowledge_base:programming:python3 to knowledge_base:programming:python:python3 George Wayne | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | ====== Python Programming ====== | ||
| + | |||
| + | ===== Python Virtual Environments ===== | ||
| + | |||
| + | ==== Create virtual environment inside the project folder ==== | ||
| + | |||
| + | < | ||
| + | python -m venv .venv | ||
| + | </ | ||
| + | |||
| + | ==== Activate It ==== | ||
| + | |||
| + | < | ||
| + | .\.venv\Scripts\activate | ||
| + | </ | ||
| + | |||
| + | ==== Install Packages ==== | ||
| + | |||
| + | < | ||
| + | pip install < | ||
| + | </ | ||
| + | |||
| + | ==== Create Requirements.txt ==== | ||
| + | |||
| + | < | ||
| + | pip freeze > requirements.txt | ||
| + | </ | ||
| + | |||
| + | ==== Install Packages All at Once ==== | ||
| + | |||
| + | < | ||
| + | pip install -r requirements.txt | ||
| + | </ | ||
| + | |||
| + | ==== Deactivate ==== | ||
| + | |||
| + | < | ||
| + | deactivate | ||
| + | </ | ||
| + | |||
| + | |||
| + | |||
| + | ===== Distribute Standalone EXE using Pyinstaller ===== | ||
| + | |||
| + | **Note: It is highly recommended to download the Python program from python.org directly. Python installed from Microsoft Store may have issues (speaking from my personal experience when wxPython was used)** | ||
| + | - Install pyinstaller package '' | ||
| + | - Execute '' | ||
| + | |||
| + | ===== Regular Expression ===== | ||
| + | |||
| + | https:// | ||
| + | |||
| + | ===== Threading ===== | ||
| + | |||
| + | https:// | ||
| + | |||
| + | ===== Pandas Dataframe Multiindexing ===== | ||
| + | |||
| + | https:// | ||
| + | |||
| + | ===== My NTAG, I2C, Wifi, Subprocess, Timeout, Argparsing Example ===== | ||
| + | **tested on Raspbian Jessie** | ||
| + | < | ||
| + | # | ||
| + | import smbus | ||
| + | import math | ||
| + | import re | ||
| + | import subprocess | ||
| + | import shlex | ||
| + | import os | ||
| + | import time | ||
| + | import signal | ||
| + | import functools | ||
| + | import argparse | ||
| + | |||
| + | # common i2c functions are: | ||
| + | # read_byte(addr) | ||
| + | # write_byte(addr, | ||
| + | # read_byte_data(addr, | ||
| + | # write_byte_data(addr, | ||
| + | # read_word_data(addr, | ||
| + | # write_word_data(addr, | ||
| + | # read_i2c_block_data(addr, | ||
| + | # write_i2c_block_data(addr, | ||
| + | |||
| + | class TimedOut(Exception): | ||
| + | pass | ||
| + | |||
| + | def call_with_timeout(timeout, | ||
| + | """ | ||
| + | f returns, raise TimedOut. The exception is raised asynchronously, | ||
| + | so data structures being updated by f may be in an inconsistent state. | ||
| + | """ | ||
| + | def handler(signum, | ||
| + | raise TimedOut(" | ||
| + | |||
| + | old = signal.signal(signal.SIGALRM, | ||
| + | try: | ||
| + | signal.alarm(timeout) | ||
| + | try: | ||
| + | return f(*args, **kwargs) | ||
| + | finally: | ||
| + | signal.alarm(0) | ||
| + | finally: | ||
| + | signal.signal(signal.SIGALRM, | ||
| + | |||
| + | def with_timeout(timeout): | ||
| + | """ | ||
| + | number of seconds. | ||
| + | """ | ||
| + | def decorator(f): | ||
| + | @functools.wraps(f) | ||
| + | def wrapped(*args, | ||
| + | return call_with_timeout(timeout, | ||
| + | return wrapped | ||
| + | return decorator | ||
| + | |||
| + | # def run_program(rcmd): | ||
| + | # Runs a program, and it's parameters (e.g. rcmd = 'ls -lh / | ||
| + | # Returns output if sucessful, or None and logs error if not. | ||
| + | @with_timeout(50) | ||
| + | def run_program(rcmd, | ||
| + | cmd = shlex.split(rcmd) | ||
| + | try: | ||
| + | proc = subprocess.Popen(cmd, | ||
| + | if (wpacli): | ||
| + | for line in iter(proc.stdout.readline, | ||
| + | line = line.decode(' | ||
| + | if (re.search(r' | ||
| + | print(line, | ||
| + | scanned = re.search(r" | ||
| + | if (scanned): print(' | ||
| + | elif (re.search(r' | ||
| + | print(line, | ||
| + | break | ||
| + | elif (re.search(r' | ||
| + | print(line, | ||
| + | # break # not connected but could be another ssid to try | ||
| + | elif (re.search(r' | ||
| + | re.search(r' | ||
| + | re.search(r' | ||
| + | elif (re.search(r'< | ||
| + | resp = proc.communicate(input=b' | ||
| + | else: | ||
| + | resp = proc.communicate() | ||
| + | except TimedOut: | ||
| + | print(' | ||
| + | proc.terminate() | ||
| + | resp = proc.communicate() | ||
| + | finally: | ||
| + | return resp | ||
| + | |||
| + | # Function to put credentials to / | ||
| + | # Returns True if updated or added, False if nothing to do | ||
| + | def addwpa(ssid, | ||
| + | if (not ssid or not psk): return | ||
| + | try: | ||
| + | f = open('/ | ||
| + | wpafile = f.read() | ||
| + | pattern = r' | ||
| + | # | ||
| + | network = re.search(pattern, | ||
| + | if (network): # update exiting network | ||
| + | oldpsk = network.group(2) | ||
| + | if (psk != oldpsk): # only do work if needed | ||
| + | substr = r' | ||
| + | newfile = re.subn(pattern, | ||
| + | f = open('/ | ||
| + | f.write(newfile[0]) | ||
| + | f.close() | ||
| + | print(' | ||
| + | return True | ||
| + | else: | ||
| + | print(' | ||
| + | return False | ||
| + | else: # add new network | ||
| + | newnet = ' | ||
| + | f = open('/ | ||
| + | f.write(newnet) | ||
| + | f.close() | ||
| + | print(' | ||
| + | return True | ||
| + | except (OSError, IOError) as err: | ||
| + | print(err) | ||
| + | |||
| + | def read_ntag(): | ||
| + | bus = smbus.SMBus(1) | ||
| + | addr = 0x55 | ||
| + | block1 = bus.read_i2c_block_data(addr, | ||
| + | try: | ||
| + | if (block1[1] == 0xFF and block[2] != 0xD1): | ||
| + | raise ValueError(' | ||
| + | if (block1[2] != 0xD1): raise ValueError(' | ||
| + | if (block1[5] != 0x54): raise ValueError(' | ||
| + | recordlen = block1[4] | ||
| + | payload = block1[9: | ||
| + | i = 0x2 | ||
| + | while i <= 0x2 + math.floor((recordlen-9)/ | ||
| + | block = bus.read_i2c_block_data(addr, | ||
| + | payload = payload + block | ||
| + | i = i+1 | ||
| + | # | ||
| + | del payload[recordlen-2: | ||
| + | if (payload[recordlen-3] != 0xFE): | ||
| + | raise ValueError(' | ||
| + | del payload[recordlen-3: | ||
| + | payload = '' | ||
| + | value = re.findall(r' | ||
| + | if (len(value)< | ||
| + | return value[0][1], | ||
| + | except ValueError as err: | ||
| + | print(err) | ||
| + | finally: | ||
| + | bus.close() | ||
| + | |||
| + | |||
| + | |||
| + | # main function | ||
| + | def main(): | ||
| + | parser = argparse.ArgumentParser() | ||
| + | parser.add_argument(' | ||
| + | args = parser.parse_args() | ||
| + | |||
| + | username, password = read_ntag() | ||
| + | if (args.force or addwpa(username, | ||
| + | # re-start wpa_supplicant | ||
| + | print(' | ||
| + | if (not os.path.isfile('/ | ||
| + | print(' | ||
| + | resp = run_program(' | ||
| + | for x in list(map(lambda x: x.decode(' | ||
| + | # | ||
| + | else: | ||
| + | print(' | ||
| + | resp = run_program(' | ||
| + | for x in list(map(lambda x: x.decode(' | ||
| + | time.sleep(3) | ||
| + | print(' | ||
| + | resp = run_program(' | ||
| + | for x in list(map(lambda x: x.decode(' | ||
| + | resp = run_program(' | ||
| + | for x in list(map(lambda x: x.decode(' | ||
| + | resp = run_program(' | ||
| + | for x in list(map(lambda x: x.decode(' | ||
| + | print(' | ||
| + | time.sleep(10) | ||
| + | ipaddr = subprocess.check_output([' | ||
| + | print(' | ||
| + | else: print(' | ||
| + | print(' | ||
| + | |||
| + | if __name__ == ' | ||
| + | main() | ||
| + | </ | ||
| + | |||
| + | ===== Subprocess and Wifi ===== | ||
| + | |||
| + | < | ||
| + | # | ||
| + | # -*- coding: utf-8 -*- | ||
| + | # [email protected] / @glennzw | ||
| + | # Handle wireless networking from Python | ||
| + | # The name (evil.py) is a play on ' | ||
| + | from subprocess import Popen, call, PIPE | ||
| + | import errno | ||
| + | from types import * | ||
| + | import logging | ||
| + | import sys | ||
| + | import logging | ||
| + | import time | ||
| + | import argparse | ||
| + | import re | ||
| + | import shlex | ||
| + | |||
| + | SUPPLICANT_LOG_FILE = " | ||
| + | |||
| + | """ | ||
| + | This bit of code allows you to control wireless networking | ||
| + | via Python. I chose to encapsualte wpa_supplicant because | ||
| + | it has the most consistent output with greatest functionality. | ||
| + | |||
| + | Currently supports OPEN, WPA[2], and WEP. | ||
| + | |||
| + | #e.g: | ||
| + | |||
| + | >>> | ||
| + | >>> | ||
| + | >>> | ||
| + | >>> | ||
| + | >>> | ||
| + | True | ||
| + | >>> | ||
| + | >>> | ||
| + | True | ||
| + | |||
| + | """ | ||
| + | |||
| + | logging.basicConfig(level=logging.DEBUG, | ||
| + | format=' | ||
| + | datefmt=' | ||
| + | filename=' | ||
| + | filemode=' | ||
| + | |||
| + | |||
| + | def run_program(rcmd): | ||
| + | """ | ||
| + | Runs a program, and it's paramters (e.g. rcmd=" | ||
| + | Returns output if successful, or None and logs error if not. | ||
| + | """ | ||
| + | |||
| + | cmd = shlex.split(rcmd) | ||
| + | executable = cmd[0] | ||
| + | executable_options=cmd[1: | ||
| + | |||
| + | try: | ||
| + | proc = Popen(([executable] + executable_options), | ||
| + | response = proc.communicate() | ||
| + | response_stdout, | ||
| + | except OSError, e: | ||
| + | if e.errno == errno.ENOENT: | ||
| + | logging.debug( " | ||
| + | else: | ||
| + | logging.error( "O/S error occured when trying to run ' | ||
| + | except ValueError, e: | ||
| + | logging.debug( "Value error occured. Check your parameters." | ||
| + | else: | ||
| + | if proc.wait() != 0: | ||
| + | logging.debug( " | ||
| + | return response | ||
| + | else: | ||
| + | logging.debug( " | ||
| + | return response_stdout | ||
| + | |||
| + | |||
| + | def start_wpa(_iface): | ||
| + | """ | ||
| + | Terminates any running wpa_supplicant process, and then starts a new one. | ||
| + | """ | ||
| + | run_program(" | ||
| + | time.sleep(1) | ||
| + | run_program(" | ||
| + | |||
| + | def get_wnics(): | ||
| + | """ | ||
| + | Kludgey way to get wireless NICs, not sure if cross platform. | ||
| + | """ | ||
| + | r = run_program(" | ||
| + | ifaces=[] | ||
| + | for line in r.split(" | ||
| + | if " | ||
| + | ifaces.append( line.split()[0] ) | ||
| + | return ifaces | ||
| + | |||
| + | |||
| + | |||
| + | def get_networks(iface, | ||
| + | """ | ||
| + | Grab a list of wireless networks within range, and return a list of dicts describing them. | ||
| + | """ | ||
| + | while retry > 0: | ||
| + | if " | ||
| + | networks=[] | ||
| + | r = run_program(" | ||
| + | if " | ||
| + | for line in r.split(" | ||
| + | b, fr, s, f = line.split()[: | ||
| + | ss = " " | ||
| + | networks.append( {" | ||
| + | return networks | ||
| + | retry-=1 | ||
| + | logging.debug(" | ||
| + | time.sleep(0.5) | ||
| + | logging.error(" | ||
| + | |||
| + | |||
| + | def _disconnect_all(_iface): | ||
| + | """ | ||
| + | Disconnect all wireless networks. | ||
| + | """ | ||
| + | lines = run_program(" | ||
| + | if lines: | ||
| + | for line in lines[1: | ||
| + | run_program(" | ||
| + | |||
| + | |||
| + | def connect_to_network(_iface, | ||
| + | """ | ||
| + | Associate to a wireless network. Support _type options: | ||
| + | *WPA[2], WEP, OPEN | ||
| + | """ | ||
| + | _disconnect_all(_iface) | ||
| + | time.sleep(1) | ||
| + | if run_program(" | ||
| + | if run_program(' | ||
| + | if _type == " | ||
| + | run_program(" | ||
| + | run_program(" | ||
| + | elif _type == " | ||
| + | run_program(' | ||
| + | elif _type == " | ||
| + | run_program(" | ||
| + | else: | ||
| + | logging.error(" | ||
| + | | ||
| + | run_program(" | ||
| + | | ||
| + | def is_associated(_iface): | ||
| + | """ | ||
| + | Check if we're associated to a network. | ||
| + | """ | ||
| + | if " | ||
| + | return True | ||
| + | return False | ||
| + | |||
| + | def has_ip(_iface): | ||
| + | """ | ||
| + | Check if we have an IP address assigned | ||
| + | """ | ||
| + | status = run_program(" | ||
| + | r = re.search(" | ||
| + | if r: | ||
| + | return r.group(1) | ||
| + | return False | ||
| + | |||
| + | def do_dhcp(_iface): | ||
| + | """ | ||
| + | Request a DHCP lease. | ||
| + | """ | ||
| + | run_program(" | ||
| + | |||
| + | |||
| + | def main(): | ||
| + | print "[--- EViL. Python wireless network manager. ---]" | ||
| + | print " | ||
| + | parser = argparse.ArgumentParser() | ||
| + | parser.add_argument(" | ||
| + | parser.add_argument(" | ||
| + | parser.add_argument(" | ||
| + | parser.add_argument(" | ||
| + | parser.add_argument(" | ||
| + | parser.add_argument(" | ||
| + | parser.add_argument(" | ||
| + | args = parser.parse_args() | ||
| + | |||
| + | if len(sys.argv) < 2: | ||
| + | print "[!] No options supplied. Try --help." | ||
| + | sys.exit(-1) | ||
| + | |||
| + | if args.nics: | ||
| + | nics = get_wnics() | ||
| + | if nics: | ||
| + | print "[+] Available NICs:" | ||
| + | for nic in get_wnics(): | ||
| + | print nic | ||
| + | else: | ||
| + | print "[W] No wireless interfaces found :-(" | ||
| + | elif args.list: | ||
| + | if not args.iface: | ||
| + | print "[!] Please specify interface. Use --help for help." | ||
| + | sys.exit(-1) | ||
| + | else: | ||
| + | if args.iface not in get_wnics(): | ||
| + | print "[E] Bad interface! - ' | ||
| + | sys.exit(-1) | ||
| + | print "[+] Searching for available networks..." | ||
| + | start_wpa(args.iface) | ||
| + | networks = get_networks(args.iface) | ||
| + | if networks: | ||
| + | networks = sorted(networks, | ||
| + | print "[+] Networks in range:" | ||
| + | for network in networks: | ||
| + | print " SSID: | ||
| + | print " Sig: | ||
| + | print " BSSID: | ||
| + | print " Flags: | ||
| + | print " Freq: | ||
| + | else: | ||
| + | print "[W] No wireless networks detected :-(" | ||
| + | elif args.connect: | ||
| + | if not args.iface or not args.ssid or not args.type or (args.type != " | ||
| + | print "[E] Missing options for --connect. Check --help for assistance." | ||
| + | sys.exit(-1) | ||
| + | else: | ||
| + | sys.stdout.write( "[+] Associating to ' | ||
| + | sys.stdout.flush() | ||
| + | if args.iface not in get_wnics(): | ||
| + | print "[E] No such wireless interface! - ' | ||
| + | sys.exit(-1) | ||
| + | start_wpa(args.iface) | ||
| + | connect_to_network(args.iface, | ||
| + | while not is_associated(args.iface): | ||
| + | time.sleep(1) | ||
| + | print " | ||
| + | sys.stdout.write(" | ||
| + | sys.stdout.flush() | ||
| + | do_dhcp(args.iface) | ||
| + | while not has_ip(args.iface): | ||
| + | time.sleep(1) | ||
| + | print " | ||
| + | print "[+] Associated and got lease. Hoorah." | ||
| + | |||
| + | if __name__ == " | ||
| + | main() | ||
| + | </ | ||
| + | |||
| + | ===== Resources ===== | ||
| + | |||
| + | ==== Plotly & Dash ==== | ||
| + | |||
| + | - https:// | ||
| + | - https:// | ||
| + | - https:// | ||
| + | - https:// | ||
| + | - https:// | ||
| + | - https:// | ||
| + | |||
| + | |||