Welcome to TiddlyWiki created by Jeremy Ruston, Copyright © 2007 UnaMesa Association
python tiddlywiki is born. I've been meaning to do this for a long time, finally got around to getting my old notes put up in here.
I've finally made a blog to tie together my various wiki's and projects. It can be found here:
http://warpcat.blogspot.com/
Was directed to a couple good links on Python:
*http://www.siafoo.net/article/57
**All about special {{{__methods__}}}
*http://www.siafoo.net/article/52
**Lots of tips, tricks, and hacks.
Added a new Category: [[VARIABLES]]
I already had categories for different variable types, but there were subjects that spanned types, so I thought it'd be good to have a place to collect that data. Went through all the tiddlers, and re-tagged them appropriately.
Added the new [[EXECUTION]] category, and re-tagged all appropriate tiddlers. This category is designed to capture anything to do with executing Python code.
Added the [[WEB]] category. What more is there to say? ;)
Added the [[PYGAME]] Category, since I have a feeling I'll be adding a lot more PyGame notes very soon...
Started authoring a "[[Visual Guide to Tkinter widgets]]". Good reference. Check out my blog on it here:
http://www.akeric.com/blog/?p=350
I've got my PyGame wiki live:
http://pygamewiki.tiddlyspot.com/
Originally I had started dumping PyGame into into this wiki, but I quickly saw that it could easily be its own 'subject', so it has been branched off to its own area.
Found a big'ol list here:
http://www.vrplumber.com/py3d.py
* https://www.tensorflow.org
** https://www.tensorflow.org/hub
** https://tfhub.dev/ <- helps you to search by problem domain.
*** ~TensorFlow Hub is a repository of trained machine learning models.
* https://pytorch.org
** https://pytorch.org/hub/
*** Discover and publish models to a pre-trained model repository designed for research exploration.
* https://modelzoo.co/
** Discover open source deep learning code and pretrained models.
** Collection across multiple different frameworks (Keras, ~PyTorch, Caffe...)
* https://paperswithcode.com/
** ML whitepapers and code.
https://image-net.org/
https://www.kaggle.com/c/imagenet-object-localization-challenge/overview/description
Over 14 million organized images for use with CV and ML.
AI > Machine Learning > Deep Learning
* AI : Is a technique which enables machines to mimic human behavior.
** Machine Learning : Is a subset of AI technique which use statistical methods to enabled machines to improve with experience. It uses algorithms to parse data, learn from that data, and make informed decisions based on what it has learned.
*** Deep Learning : is a particular kine of machine learning that is inspired by the functionality of our brain cels called neurons which led to the concept of artificial neural network. It structures algorithms in layers to create artificial 'neural network' that can laern and make intelligent decisions on its own.
* Data Science crosses over all three of the above. It uses data, via the above methods, to help make business decisions. It takes data, and turns it into something useful for a product or business. But where do they get the data? From Data Engineers...
** Data Analysis : A subset that allows you to analyze the data you have.
* Data Engineering : has overlap with Data Science : They're who prepare the data for the data scientists. They take all the data points from their company, and produces & maintains it in databases (for example), so the business has access to the data in an organized fashion. "Like a librarian".
Python implementations I've messed with:
* https://www.tensorflow.org/
** https://www.tensorflow.org/tutorials/
*** https://www.youtube.com/watch?v=eBbEDRsCmv4 : Video for '~TensorBoard', their debug tools
* https://eng.uber.com/introducing-ludwig/
** https://uber.github.io/ludwig/user_guide/#programatic-api
Resources (newest on the bottom):
* https://www.youtube.com/watch?v=WSbgixdC9g8
* http://karpathy.github.io/neuralnets/?fbclid=IwAR3AHXqexeHfFz9_ZptuVjF5pEKP0Lv6_IrKXzkPmpDyJkBQC-WnMqnbrOA
* http://neuralvfx.com/matchmove/reverse-matchmove-gan/
* https://3deeplearner.com/
* https://www.freecodecamp.org/news/learn-natural-language-processing-no-experience-required/
** https://www.youtube.com/watch?v=B2q5cRJvqI8
* https://www.youtube.com/channel/UCz9-ZKdsXcIqYe-jdd4pcXA
* https://freecoursesite.us/tensorflow-2-keras-deep-learning/
I started this as my online notes while I learn [[Python|http://www.python.org/]]. At the creation date of this wiki I'd define myself as a 'python noob', so the things listed are the foundations of learning the language. My background in scripting\programming is entirely self-taught: I first learned the scripting language MEL (Maya Embedded Language, for which I have it's own dedicated wiki: http://mayamel.tiddlyspot.com/) and have dabbled in Processing (http://www.processing.org/). Because of that, my approach to learning a language may be a bit different from the 'standard programmer'. I often find myself missing out on key pieces of programming lore, that take me longer than I presume normal to figure out.
I originally had this page hosted at these locations (it moved around):
*http://warpcat.pbwiki.com/HowToFindStuffInPython
*http://www.openwiki.com/ow.asp?ToFindStuffInPython
But I found the tiddlywiki style to be much easier to deal with. That page has been transfered here, and expanded upon.
''DISCLAIMER''
*I can't be blamed for anything misrepresented on this page! If it doesn't work, no finger-waving my direction.
*If you find something wrong, please tell me. I //am// trying to correctly learn this stuff.
*Since I work on a Windows system, the majority of the command line stuff I call out to is Win-centric. If you're using Lunix\Unix\OSX etc, I can't comment on how well things will work.
When you have packages setup, and import modules from one subpackage into another subpackage, I've ran into edge-cases where the module doing the importing, and the root of the package of the imported module have the same name.
For example, given setup of two packages, {{{packageA}}} and {{{someName}}}:
*\root
**\packageA
***{{{__init__.py}}}
***\subpackageA
****{{{__init__.py}}}
****@@{{{someName.py}}}@@
**@@\someName@@
***{{{__init__.py}}}
***\someOtherName
****{{{__init__.py}}}
****{{{greatName.py}}}
Let's say you're authoring {{{packageA.subpackageA.someName.py}}}, and you want to import {{{someName.someOtherName.greatName.py}}}: When you do your import like so:
{{{
# packageA.subpackageA.someName.py
from someName.someOtherName import greatName as great
}}}
The module tries to import //itself// ({{{import someName.}}}), and then errors when it can't find the attribute {{{.someOtherName}}} in itself.
To work around this, I've used the {{{__import__}}} function with success:
http://docs.python.org/library/functions.html#__import__
{{{
# packageA.subpackageA.someName.py
_temp = __import__('someName.someOtherName', locals(), globals, ['greatName'], 0)
great = _temp.greatName
}}}
The last zero in the argument list tells the function to make this an //absolute//, rather than relative, import.
----
Another solution is via the {{{imp}}} module:
{{{
import imp
module = imp.load_source('someName.someOtherName.greatName', 'c:/root/someName/someOtherName/greatName.py')
}}}
The first arg will be the unique name of the module in Python, defined by you. The second arg is the full path to the actual module to import. Note that the {{{imp.load_source}}} also reloads the module after import.
----
Also see:
*[[How can I execute Python code outside the Python path?]]
*[[Importing a module by full path]]
Update:
<<<
Recently found this blog post:
http://pysnippet.blogspot.com/2010/05/abcs-abstract-base-classes.html
That talks about the 'Abstract Base Class' module, which I was unaware of when authoring my system below. But they have similarities. [[docs|http://docs.python.org/library/abc.html]]
<<<
----
At the time of this authoring, abstract methods are on the periphery of my knowledge-base ;)
As I understand it, 'abstract methods' are methods implemented by a superclass '[[interface|Implementing interfaces]]' (borrowing terminology from some other languages, like Java). The abstract method doesn't do anything, but it's existence means that a subclass needs to implement it. It's a way, in my mind, of enforcing polymorphism.
To aid in making sure this is properly communicated to the user, you can use the {{{NotImplementedError}}} exception, for which the [[docs|http://docs.python.org/library/exceptions.html#exceptions.NotImplementedError]] on it say:
>In user defined base classes, abstract methods should raise this exception when they require derived classes to override the method.
In the below example, I illustrate this via a self-made [[decorator]]: In your superclass, you wrapper your abstract methods with the {{{@abstract}}} decorator. If the user calls to one of these abstract methods, it will raise a {{{NotImplementedError}}} exception. But if a subclass has overwritten the abstract method with it's own, it will obviously work:
{{{
def abstract(func):
"""
This will be used as a decorator (@abstract) to create abstract methods.
"""
def notImplemented(*args):
raise NotImplementedError(func)
return notImplemented
class Spam(object):
# Our superclass, with abstract method.
@abstract
def myMethod(self):
pass
class SubSpam(Spam):
# Our subclass, that replaces the abstract method with a valid one.
def myMethod(self):
print "Replaced abstract method!"
eggs = Spam()
subEggs = SubSpam()
}}}
{{{
eggs.myMethod()
# NotImplementedError: <function myMethod at 0x000000000371F2E8>
}}}
{{{
subEggs.myMethod()
# Replaced abstract method!
}}}
----
Also see:
*[[Implementing interfaces]]
Found this post:
http://coreygoldberg.blogspot.com/2011/07/python-processing-gmail-imap-email.html
By Cory Goldberg, that makes it really darn easy to access your gmail. Code reproduced below:
{{{
import imaplib
USER = 'username@gmail.com'
PASSWORD = 'xxx'
mail = imaplib.IMAP4_SSL('imap.gmail.com', 993)
mail.login(USER, PASSWORD)
mail.select('Inbox')
status, data = mail.search(None, 'ALL')
for num in data[0].split():
status, data = mail.fetch(num, '(RFC822)')
print 'Message %s\n%s\n' % (num, data[0][1])
mail.close()
mail.logout()
}}}
And here's the docs for {{{imaplib}}}
http://docs.python.org/library/imaplib.html
The Python module [[ctypes|http://docs.python.org/library/ctypes.html]] is a good interface into grabbing data from Windows (the OS) itself.
And example is given here, for querying the location of a window on screen (search down for the {{{GetWindowRect}}} section)
http://docs.python.org/library/ctypes.html#function-prototypes
Let's break it down (based on my powers of deduction...):
Here's what the Windows ref say about the {{{GetWindowRef()}}} function:
{{{
BOOL GetWindowRect(
HWND hWnd,
LPRECT lpRect
);
}}}
So, it returns a {{{boolean}}}, and takes two args, {{{hWnd}}}, and {{{lpRect}}}
This is the Python documentation implementation:
{{{
from ctypes import POINTER, WINFUNCTYPE, windll
from ctypes.wintypes import BOOL, HWND, RECT
prototype = WINFUNCTYPE(BOOL, HWND, POINTER(RECT)) #1
paramflags = (1, "hwnd"), (2, "lprect") #2
GetWindowRect = prototype(("GetWindowRect", windll.user32), paramflags) #3
}}}
*1 : {{{prototype = WINFUNCTYPE(BOOL, HWND, POINTER(RECT)) }}}
**Create a {{{WINFUNCTYPE}}} (see [[docs|http://docs.python.org/library/ctypes.html#function-prototypes]]) function object (called {{{prototype}}}), for which apparently the first arg is the return type, and consecutive args are the args to that function.
**{{{ctypes.WINFUNCTYPE(restype, *argtypes, use_errno=False, use_last_error=False)}}}
*2 : {{{paramflags = (1, "hwnd"), (2, "lprect")}}}
**Create the {{{paramflags}}} arguments we will pass into this {{{ctype}}} function. From the docs:
<<<
paramflags must be a tuple of the same length as argtypes.
Each item in this tuple contains further information about a parameter, it must be a tuple containing one, two, or three items.
The first item is an integer containing a combination of direction flags for the parameter:
*1 : Specifies an input parameter to the function.
*2 : Output parameter. The foreign function fills in a value.
*4 : Input parameter which defaults to the integer zero.
The optional second item is the parameter name as string. If this is specified, the foreign function can be called with named parameters.
The optional third item is the default value for this parameter.
<<<
*3 : {{{GetWindowRect = prototype(("GetWindowRect", windll.user32), paramflags)}}}
**Create our {{{GetWindowRect}}} object. There are four different ways to call to a {{{prototype}}} object:
***{{{prototype(address)}}}
****Returns a foreign function at the specified address which must be an integer.
***{{{prototype(callable)}}}
****Create a C callable function (a callback function) from a Python callable.
***{{{prototype(func_spec[, paramflags])}}} {{{<--}}} ''The one we're using.''
****Returns a foreign function exported by a shared library. func_spec must be a 2-tuple (name_or_ordinal, library). The first item is the name of the exported function as string, or the ordinal of the exported function as small integer. The second item is the shared library instance.
***{{{prototype(vtbl_index, name[, paramflags[, iid]])}}}
**** Returns a foreign function that will call a COM method. vtbl_index is the index into the virtual function table, a small non-negative integer. name is name of the COM method. iid is an optional pointer to the interface identifier which is used in extended error reporting. COM methods use a special calling convention: They require a pointer to the COM interface as first argument, in addition to those parameters that are specified in the argtypes tuple.
Now that we finally have a {{{getWindowRect}}} object, we can instance it:
{{{
# and example of getting 'hwnd' from Pygame:
hwnd = pygame.display.get_wm_info()["window"]
rect = GetWindowRect(hwnd)
}}}
And once instanced, we can access it's attrs:
{{{
print "top, left, bottom, right: ", rect.top, rect.left, rect.bottom, rect.right
}}}
----
Using that example, here are more Windows functions that can be accessed by {{{ctypes}}}
http://msdn.microsoft.com/en-us/library/dd469351%28VS.85%29.aspx
I wonder how much data can be pulled from the [[WINDOWINFO|http://msdn.microsoft.com/en-us/library/ms632610%28VS.85%29.aspx]] structure?
You need:
*[[pywin32|http://sourceforge.net/projects/pywin32/]], also known as 'Python for windows extensions'
*[[comtypes|http://sourceforge.net/projects/comtypes/]], or you need this.
You probably want:
*[[winshell|http://timgolden.me.uk/python/winshell.html]]
----
Nice blog on how to make Windows shortcuts:
http://www.blog.pythonlibrary.org/2010/01/23/using-python-to-create-shortcuts/
----
Recipe and blog post on gathering Windows information (that actually //doesn't// require the above modules)
http://code.activestate.com/recipes/511491/
http://www.blog.pythonlibrary.org/2010/01/27/getting-windows-system-information-with-python/
http://www.blog.pythonlibrary.org/2010/02/06/more-windows-system-information-with-python/
http://www.blog.pythonlibrary.org/2010/02/06/lock-down-windows-with-python/ (more registry stuff)
----
!~PySide2
If you have ~PySide or ~PySide2 installed, very easy:
{{{
from PySide2 import QtGui
def copy(text):
QtGui.QClipboard().setText(text)
def paste():
return QtGui.QClipboard().text()
}}}
!pyperclip:
http://coffeeghost.net/2010/10/09/pyperclip-a-cross-platform-clipboard-module-for-python/
Uses code similar to the {{{ctypes}}} example below.
!ctypes:
Example from:
http://stackoverflow.com/questions/579687/how-do-i-copy-a-string-to-the-clipboard-on-windows-using-python
This is pretty cool, since it uses no external libs, only [[ctypes|http://docs.python.org/library/ctypes]]
Had to modify {{{paste}}}, since it appears to be original written for Python 3.0 (I'm on 2.6)
{{{
import ctypes
#Get required functions, strcpy..
strcpy = ctypes.cdll.msvcrt.strcpy
ocb = ctypes.windll.user32.OpenClipboard #Basic Clipboard functions
ecb = ctypes.windll.user32.EmptyClipboard
gcd = ctypes.windll.user32.GetClipboardData
scd = ctypes.windll.user32.SetClipboardData
ccb = ctypes.windll.user32.CloseClipboard
ga = ctypes.windll.kernel32.GlobalAlloc # Global Memory allocation
gl = ctypes.windll.kernel32.GlobalLock # Global Memory Locking
gul = ctypes.windll.kernel32.GlobalUnlock
GMEM_DDESHARE = 0x2000
def get():
ocb(None) # Open Clip, Default task
pcontents = gcd(1) # 1 means CF_TEXT.. too lazy to get the token thingy ...
data = ctypes.c_char_p(pcontents).value
#gul(pcontents) ?
ccb()
return data
def paste(data):
ocb(None) # Open Clip, Default task
ecb()
try:
hCd = ga(GMEM_DDESHARE, len(bytes(data))+1) # Python 2
except TypeError:
hCd = ga(GMEM_DDESHARE, len(bytes(data,"ascii"))+1) # Python 3
pchData = gl(hCd)
try:
strcpy(ctypes.c_char_p(pchData), bytes(data))
except TypeError:
strcpy(ctypes.c_char_p(pchData), bytes(data,"ascii"))
gul(hCd)
scd(1,hCd)
ccb()
}}}
!Tkinter
Example from:
http://stackoverflow.com/questions/579687/how-do-i-copy-a-string-to-the-clipboard-on-windows-using-python
This is nice, since it uses [[Tkinter|http://docs.python.org/library/tkinter.html]] which ships with Python, and is less code than ctypes:
{{{
from Tkinter import Tk
r = Tk()
r.withdraw()
r.clipboard_clear()
r.clipboard_append('i can has clipboardz?')
r.destroy()
}}}
!{{{win32clipboard}}}
If {{{win32clipboard}}} isn't part of your standard install, you can download it here as part of the 'pywin32' extension for Windows here:
http://sourceforge.net/projects/pywin32/
It seems to come standard with the ~ActiveState '~ActivePython' distribution here, if you use that distib:
http://www.activestate.com/activepython/
----
From:
http://snippets.dzone.com/posts/show/724
{{{
import win32clipboard as w
import win32con
def getText():
w.OpenClipboard()
d=w.GetClipboardData(win32con.CF_TEXT)
w.CloseClipboard()
return d
def setText(aType,aString):
w.OpenClipboard()
w.EmptyClipboard()
w.SetClipboardData(aType,aString)
w.CloseClipboard()
}}}
From:
http://mail.python.org/pipermail/python-list/2007-June/617808.html
{{{
from win32clipboard import *
OpenClipboard()
EmptyClipboard()
SetClipboardText("Hello from Python!")
CloseClipboard()
}}}
----
And here's a function I came up with for pasting to the clipboard:
{{{
import win32clipboard as w32c
def pasteToClipboard(stuff):
"""
Paste the passed in data to the windows clipboard
stuff : string or list : data to paste to clipboard
"""
if type(stuff) != type([]):
stuff = [stuff]
paste = '\n'.join(stuff)
w32c.OpenClipboard()
w32c.EmptyClipboard()
w32c.SetClipboardText(paste)
w32c.CloseClipboard()
}}}
(On the Windows system at least...) this directory is stored in the system variable {{{TMP}}} or {{{TEMP}}}.
----
Create a name for a file in the users temp directory:
{{{
import os
# TMPDIR variable on mac
tempfile = os.path.join(os.getenv("TMP"), "tempfile.txt")
print tempfile
}}}
On Vista:
{{{
C:\Users\<USERNAME>\AppData\Local\Temp\tempfile.txt
}}}
On Mac:
{{{
/var/folders/kv/dk8t43d535s3pvw9z_8zhh2c0000gn/T/tempfile.ma
}}}
----
For a more platform indipendent way:
{{{
import tempfile
tempDir = tempfile.gettempdir()
C:\Users\User.Name\AppData\Local\Temp
}}}
----
http://docs.python.org/library/tempfile.html
http://blog.doughellmann.com/2008/02/pymotw-tempfile.html
Normally when adding things to a dict you use the '{{{=}}}' assignment operator. But if you're trying to update a dict in something like a {{{lambda}}}, you can't use the '{{{=}}}' assignment operator. To work around this, you can use the {{{update}}} method:
{{{
d = {}
# Using the assignment operator:
d["A"] = 1
# Using the update method:
d.update({"B":2})
print d
# {'A': 1, 'B': 2}
}}}
Had a problem where I had many lists of numbers, and needed a way to combine them into new lists based on their shared elements: For example, if these two lists were passed in: {{{[[1,2,3], [3,4,5]]}}} the tool would return the combined {{{[1,2,3,4,5]}}} : Since both lists share the int 3, they're combined.
This is the solution I came up with, being unable to properly articulate my problem to Google and find it online:
{{{
def combineSimilarElements(data):
"""
Based on the passed in data (list of lists), combine them into the fewest
possible number of items that have the same shared elements.
Parameters:
data : list : List of sublists. The sublists will be compared to one another.
Return : list : The combination of data.
"""
# Need to copy, otherwise we'll modify in-place:
retData = data[:]
intermediateData = []
curSize = len(retData)
prevSize = -1
while curSize != prevSize:
while len(retData):
currentCheck = retData.pop(0)
for data in retData:
# Check for intersection/shared items:
if set(currentCheck) & set(data):
currentCheck = list(set(currentCheck).union(set(data)))
retData.remove(data)
intermediateData.append(currentCheck[:])
prevSize = curSize
retData = intermediateData
intermediateData = []
curSize = len(retData)
return retData
}}}
{{{
data = [[1,2,3,4],
[4,5,6,7],
[8,9,10,11],
[11,12,13,14],
[17,25,19,30],
[34,86,72,25]]
results = combineSimilarElements(data)
print results
}}}
{{{
[[1, 2, 3, 4, 5, 6, 7],
[8, 9, 10, 11, 12, 13, 14],
[34, 72, 17, 19, 86, 25, 30]]
}}}
Algorithm I wrote for a buddy after a lot of back and forth. He had list of hundreds of thousands of items that needed to be filtered. The idea was there are two lists: The "items" could be any arbitrary strings. There is another list of equal length, that has a number assigned to each item. The end result needs to be a list of tuples: Each tuple is an item, and the highest count found. Attention was paid to speed: Minimizing looping, only use builtins. I started with a much less efficient version that worked fine for hundreds of items, but when it hit hundreds of thousands it was painfully (hours) slow. This version would crunch out the sets in just over a minute.
{{{
def findHighestItemCounts(items, counts):
"""
Parameters:
items : list : List of items.
counts : list : List of ints. Must match len(items)
Return : List : List of tuples. Each tuple has an item from items, and the
highest number of times it was counted.
"""
keys = set(items)
dic = dict.fromkeys(keys)
for i,key in enumerate(items):
if dic[key] and counts[i] > dic[key][-1]:
dic[key].append(counts[i])
elif not dic[key]:
dic[key] = [counts[i]]
result = [(key, dic[key][-1]) for key in dic]
return result
}}}
{{{
items = ["A", "B", "C", "D", "A", "B", "C", "A", "B", "A"]
counts = [ 6, 2, 5, 3, 1, 4, 3, 2, 6, 7 ]
results = findHighestItemCounts(items, counts)
print results
# [('A', 7), ('C', 5), ('B', 6), ('D', 3)]
}}}
* Original Author: https://twitter.com/exutumno
** https://github.com/mxgmn/WaveFunctionCollapse
Python implementations:
* https://github.com/robert/wavefunction-collapse
** https://robertheaton.com/2018/12/17/wavefunction-collapse-algorithm/ <-- Great overview
* https://github.com/ikarth/wfc_2019f
* https://github.com/ikarth/wfc_python
* https://github.com/lamelizard/GraphWaveFunctionCollapse
Below are a list of //all// the subjects (tiddlers) in the wiki. Note that there will be ones for site maintenance etc, that should be disregarded.
----
<<list all>>
https://www.anaconda.com/
Is a Python distribution manager, like [[Virtualenv : Basics]].
It allows you to stand up multiple 'environments' each with their own cut of Python, and dependency packages. This way, rather than having a single install of Python on your PC that all your modules/packages need to share, this is a like a 'custom version of Python //per module/package//'.
!Download Miniconda:
* https://docs.conda.io/en/latest/miniconda.html
!Terms
* Anaconda : The 'whole distribution' (3GBish)
** All available packages: https://docs.anaconda.com/anaconda/packages/pkg-docs/
* ~MiniConda : A subset of Anaconda where you can choose the modules.
* Conda : The command prompt/terminal you use.
!High Level usage:
!!Set Your Conda Install Location:
You can find docs on the default location here: https://docs.anaconda.com/anaconda/user-guide/faq/
Which are:
* Windows 10: {{{C:\Users\USERNAME\miniconda3}}}
* macOS: {{{/Users/USERNAME/miniconda3}}} for the shell install, {{{~/opt}}} for the graphical install. See installing on macOS.
* Linux: {{{/home/USERNAME/miniconda3}}}
Wherever you install it (examples below), you should add these two paths to your PATHS env var: The base install dir, and its {{{\Scripts}}} subdir:
{{{
C:\Users\USERNAME\miniconda3
C:\Users\USERNAME\miniconda3\Scripts
}}}
This will let you access both the conda.exe and conda's 'base' environment python.exe from the cmd shell (but you really shouldn't ever access the base python.exe if you're not actually running via the Anaconda Prompt).
!! Define Your Custom environment locations:
Define where you'll be storing your personal conda environments.
The default location is here, if you don't specify a path:
{{{
C:\Users\USERNAME\.conda\envs
}}}
But you can tell them to go anywhere you want (examples below):
{{{
C:\blah\blah\anaconda\envs
}}}
!!Fire up a new Conda terminal:
* On windows, search for the {{{ ‘Anaconda Prompt (Miniconda3)’}}}, to access that terminal.
* Based on different installs, I've seen different arguments to launch that shortcut:
{{{
%windir%\System32\cmd.exe "/K" C:\ProgramData\Miniconda3\Scripts\activate.bat C:\ProgramData\Miniconda3
}}}
{{{
%windir%\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy ByPass -NoExit -Command "& 'C:\Users\USERNAME\miniconda3\shell\condabin\conda-hook.ps1' ; conda activate 'C:\Users\USERNAME\miniconda3' "
}}}
* When launched:
** {{{(base)}}} is the default environment.
** When you 'activate' new environments, the name in the parenthesis will change to show you the environment you're in.
All the below examples expect to be ran from the Conda terminal.
!!!Create a new Conda a environment
* If you're using a custom location for your enviornments, make a sub-folder for your new environment, say:
** {{{C:\Users\USERNAME\Documents\python\anaconda\sample_project_1}}}
* But if you're going to use the Conda default \env location, you won't need to do this.
* Open Codna a terminal per above.
* Cd into the project folder you just made (if you're using a custom install path).
* Create a new environment, specifying where those files will be saved {{{./env}}}, then list the multiple packages that should be installed with it:
** {{{> conda create --prefix ./env pandas numpy matplotlib scikit-learn jupyter}}}
* Or, if you're using the default location to install the new env (showing how to use a specific version of Python):
** {{{> conda create --name sample_project_1 python=3.7}}}
** Note: If you don't specify the version of Python, that environment will use the same version as the 'base' env.
* After created, conda should print the code you can use to activate it in the future, like either of these (based on the method you used to make it):
** {{{> conda activate C:\Users\USERNAME\Documents\python\anaconda\sample_project_1\env}}}
** {{{> conda activate sample_project_1}}}
* Note, for custom project paths::
** The root of your project/environment is here: {{{\sample_project_1}}}
*** This is where (for example) your Jupyter Notebooks would be saved, your data files placed.
** But the 'environment' that 'Conda activates' (below) is the {{{\sample_project_1\env}}} subfolder : This is where it installs all the Python packages.
!!! Activate an environment
* If you're using a custom env path:
** Optional, but convenient: (But not the {{{\env}}} subfolder)
{{{
cd conda activate C:\Users\USERNAME\Documents\python\anaconda\sample_project_1
}}}
* Run the activation code given to you when you setup the environment originally:
{{{
conda activate C:\Users\USERNAME\Documents\python\anaconda\sample_project_1\env
}}}
* If you installed your env in the default location:
{{{
conda activate sample_project_1
}}}
!!! Run a Jupyter notebook/lab
You can now start (for example) a Jupyter notebook / lab in that directory:
{{{
jupyter notebook
}}}
{{{
jupyter lab
}}}
See :
* [[Jupyter Notebook : Overview]]
* [[JupyterLab : Overview]]
!!! Deactivate an environment
* Need to do this before you can activate a new environment.
{{{
conda deactivate
}}}
!!! List all your Conda environments
{{{
conda env list
}}}
List existing packages/versions
{{{
conda list
}}}
!!! Update Conda
May require admin rights
{{{
conda update conda
}}}
!!! Search For a Package:
{{{
conda search package_name
}}}
If you can find it in there, go look here: https://anaconda.org/conda-forge
!!! Install a new package:
{{{
conda install package_name
}}}
And find all packages here : https://docs.anaconda.com/anaconda/packages
!!! Update a package:
{{{
conda update packageName
}}}
!!! Export an environment:
{{{
conda env export > environment.yml
}}}
it collects all the requirements for this environments.
!!! Create a new env from an {{{environment.yml}}}
First, like above, make your root project folder, and cd into it in a shell. Then:
{{{
conda env create --prefix ./env -f ../relative/path/to/environment.yml
}}}
Which will bot crate the {{{/env}}} subfolder, and create that new environment based on the provided path to {{{environment.yml}}}.
! Cheat Sheet
[[Conda 4.6.0|https://docs.conda.io/projects/conda/en/4.6.0/_downloads/52a95608c49671267e40c689e0bc00ca/conda-cheatsheet.pdf]]
! Execute a certain environments python.exe on a given module:
This can be ran from a regular shell, not a conda prompt, since it calls //to// conda.exe (presuming the {{{conda.exe}}} is on your PATH, if not, you'll need to provide the full path to it too):
{{{
> conda run -n myEnvName python c:/full/path/to/moduleNameHere.py
}}}
! Open An Anaconda Prompt With An Environment Auto Activated
On Windows, you can create a shortcut that will launch the Anaconda Prompt, that auto-activates a given environment in the process. Here's an example, presuming your environment {{{myEnvName}}} lives under the {{{/Miniconda3/envs}}} dir. Otherwise you can provide the full path to your env.
{{{
%windir%\System32\cmd.exe "/K" C:\Miniconda3\Scripts\activate.bat myEnvName
}}}
! Activate a conda environment and run a module in it via Python:
{{{
import subprocess
module = r"c:\path\to\my\module.py
environment = "myAwesomeEnv"
subprocess.run(r'conda activate %s && python %s && conda deactivate'%(environment, module), shell=True)
}}}
!Activate and run conda environments and python via a standard Windows shell
{{{
> call C:\path\to\Miniconda3\Scripts\activate.bat activate horizon && python c:\path\to\my\python\module.py && conda deactivate
}}}
This has the bonus of letting you see the results of the module execution in that shell, rather than hiding it.
Found here: http://nodebox.net/code/index.php/Math
{{{
from math import degrees, atan2
# 2d points:
def angle(x0, y0, x1, y1):
a = degrees( atan2(y1-y0, x1-x0) )
return a
}}}
The python {{{math}}} module is missing calls to any kind of vector math. :-( I've found a few solutions listed below. I also have some notes on doing it by hand [[here|Vector math]].
!~ActiveState recipes:
*[[Vector|http://code.activestate.com/recipes/578006-vector/]] : A fairly robust looking 2d vector solution.
!~PyGame
*~PyGame have contributed [[Vec2d|http://pygame.org/wiki/2DVectorClass]] and [[Vec3d|http://pygame.org/wiki/3DVectorClass]] classes.
!gameobjects
*Main Page: http://code.google.com/p/gameobjects/
*"Game Objects is a collection of 2D and 3D maths classes, and algorithms for helping in the creation of games with Python. Suitable for PyGame, but independent of it."
*Specifically its {{{Vector2}}} and {{{Vector3}}} classes.
!~NumPy
*Main Page: http://numpy.scipy.org/
*Documentation: http://www.tramy.us/numpybook.pdf
*Source: http://sourceforge.net/project/showfiles.php?group_id=1369&package_id=175103
!~PyEuclid
*Main Page: http://partiallydisassembled.net/euclid.html
*Documentation: http://partiallydisassembled.net/euclid/
*Source: http://code.google.com/p/pyeuclid/
It includes these data structures:
*2D and 3D Vector
*3x3 and 4x4 Matrix
*Quaternion
And these physical representations:
*Point
*Line, ray, line segment
*Circle, sphere
!~VPython
*Main Page: http://vpython.org
*Download: http://vpython.org/download.html
*Documentation: http://vpython.org/webdoc/visual/index.html
*Docs on vectors specifically: http://vpython.org/webdoc/visual/vector.html
**Includes mag, mag2, norm, cross, dot, rotate, diff_angle
Examples:
{{{
# Includes a vector object type:
from visual import *
v1 = vector(1,2,3)
v2 = vector(10,20,30)
print v1+v2
# <11, 22, 33>
print 2*v1
# <2, 4, 6>
m = v1.mag
print m
# 3.74165738677
print v1.norm()
# <0.267261, 0.534522, 0.801784>
}}}
Vector objects have these attributes:
*{{{mag}}}
*{{{mag2}}}
*{{{x}}}
*{{{y}}}
*{{{z}}}
And these methods:
*{{{astuple(...)}}}
**Convert this vector to a tuple. Same as tuple(vector), but much faster.
*{{{clear(...)}}}
**Zero the state of this vector. Potentially useful for reusing a temporary variable.
*{{{comp(...)}}}
**The scalar projection of this vector onto another.
*{{{cross(...)}}}
**The cross product of this vector and another.
*{{{diff_angle(...)}}}
**The angle between this vector and another, in radians.
*{{{dot(...)}}}
**The dot product of this vector and another.
*{{{norm(...)}}}
**The unit vector of this vector.
*{{{proj(...)}}}
**The vector projection of this vector onto another.
*{{{rotate(...)}}}
**Rotate this vector about the specified axis through the specified angle, in radians
Just a collection of reference links:
----
*http://www.pymedia.org/
**"~PyMedia is a Python module for wav, mp3, ogg, avi, divx, dvd, cdda etc files manipulations. It allows you to parse, demutiplex, multiplex, decode and encode all supported formats. It can be compiled for Windows, Linux and cygwin."
----
http://www.blog.pythonlibrary.org/2010/07/24/wxpython-creating-a-simple-media-player/
Blog showing how to use [[wxPython|http://www.wxpython.org/]], [[MPlayer|http://www.mplayerhq.hu/design7/news.html]], and [[MplayerCtrl|http://pypi.python.org/pypi/MplayerCtrl/]] to make a video-player.
----
http://lateral.netmanagers.com.ar/weblog/posts/BB905.html
Making an audio and video player with [[PyQt|http://wiki.python.org/moin/PyQt]]
https://docs.python.org/2/library/future_builtins.html
https://python-future.org/compatible_idioms.html
https://sebastianraschka.com/Articles/2014_python_2_3_key_diff.html
For print:
{{{
from __future__ import print_function
print("new print function, not old print statement")
}}}
I've been looking for ways to author SVG images in Python to support work on my Ostrich Egg-bot. Found this recipe on ~ActiveState to help me along:
*http://code.activestate.com/recipes/578123-draw-svg-images-in-python-python-recipe-enhanced-v/
**It uses the software [[ImageMagick|http://www.imagemagick.org/script/index.php]] to view them.
I need to learn this. Thus, I will put notes here!
See: [[Character and numric conversion]]
*http://docs.python.org/library/stdtypes.html#bit-string-operations-on-integer-types
*http://wiki.python.org/moin/BitManipulation
*http://compsci.ca/v3/viewtopic.php?t=9893
*http://en.wikipedia.org/wiki/Bitwise_operation
*Help from Processing docs:
**http://www.processing.org/reference/bitwiseOR.html
**http://www.processing.org/reference/bitwiseAND.html
**http://www.processing.org/reference/leftshift.html
**http://www.processing.org/reference/rightshift.html
----
----
*When doing bitwise operations in Python, you can apply the operations directly to integer values: It applies the operation on their binary equivalent, and returns the integer value.
*When thinking about bitwise operations, it helps (me at least) to relate them to sets, since they behave similarly.
----
| Operation | Result | Notes |
| | | |
| x {{{|}}} y |bitwise ''or'' of x and y |True if either bit is positive, else false. Combines bits, where 1 bits have priority. |
| x {{{^}}} y |bitwise ''exclusive or'' ('xor') of x and y |True if bits are opposite, false if the same. |
| x {{{&}}} y |bitwise ''and'' of x and y |True if both bits are positive, else false. Acts like a mask where 0 bits have priority. |
| x {{{<<}}} n |x ''shifted left'' by n bits |Each shift left multiplies by two. |
| x {{{>>}}} n |x ''shifted right'' by n bits |Each shift right divides by two. Will truncate decimals. |
| {{{~}}}x |the bits of x ''inverted''. 'Not x' |yields -(num + 1) |
| X Y | X {{{&}}} (and) Y | X {{{|}}} (or) Y | {{{~}}} (not) X | {{{~}}} (not) Y | X {{{^}}} (xor) Y |
| | | | | | |
| 1 1 | 1 | 1 | 0 | 0 | 0 |
| 1 0 | 0 | 1 | 0 | 1 | 1 |
| 0 1 | 0 | 1 | 1 | 0 | 1 |
| 0 0 | 0 | 0 | 1 | 1 | 0 |
----
!!!Combined example:
(Borrowed and modified from the Processing doc examples listed above...)
Bit shifting and manipulation is commonly used for dealing with color values. So let's store an ARGB (alpha, red, green blue) color value in 32-bits.
Each channel starts out as an int from 0-255, but then is bit-shifted into its binary format.
{{{
# Make our color values in binary format.
a = 255 << 24 # bin(a) = 11111111000000000000000000000000
r = 204 << 16 # bin(r) = 00000000110011000000000000000000
g = 204 << 8 # bin(g) = 00000000000000001100110000000000
b = 51 # bin(b) = 00000000000000000000000000110011
}}}
Now, {{{OR}}} the values together into a single 32-bit number:
{{{
# argb is now a single value storing all four a, r, g, b values:
argb = a | r | g | b # bin(argb) = 11111111110011001100110000110011
}}}
{{{
# Prove it:
print bin(a).replace('0b', '').zfill(32)
print bin(r).replace('0b', '').zfill(32)
print bin(g).replace('0b', '').zfill(32)
print bin(b).replace('0b', '').zfill(32)
print bin(argb).replace('0b', '')
}}}
{{{
11111111000000000000000000000000 # a
00000000110011000000000000000000 # r
00000000000000001100110000000000 # g
00000000000000000000000000110011 # b
11111111110011001100110000110011 # argb, values OR'd together
}}}
Convert from Binary back to 0-255 integer:
The sytax "{{{& 0xFF}}}" compares the binary representation of the two values and makes all but the last 8 bits into a 0.
"{{{0xFF}}}" is {{{00000000000000000000000011111111}}}
Meaning, it makes a mask only showing the last 8 digits. So first, the value is bit-shifted to the right by the appropriate amount, then the appropriate values are masked for the result:
{{{
a = argb >> 24 & 0xFF
r = argb >> 16 & 0xFF
g = argb >> 8 & 0xFF
b = argb & 0xFF
print a, r, g ,b
# 255 204 204 51
}}}
----
!!!Shifting examples, {{{<<}}}, {{{>>}}}
As explained above, each shift to the left multiplies the value by 2, and each shift to the right divides the value by two. Right shift (division) can be lossy, since decimal values aren't preserved.
Shifting left by 1 = val * 2
Shifting left by 2 = val * 4
Shifting left by 3 = val * 8
etc...
Shifting right by 1 = val / 2
Shifting right by 2 = val / 4
Shifting right by 3 = val / 8
etc...
{{{
intVal0 = 130
binVal0 = bin(intVal0)
intLeft1 = intVal0 << 1
binValLeft1 = bin(intLeft1)
intRight1 = intVal0 >> 1
binValRight1 = bin(intRight1)
intLeft2 = intVal0 << 2
binValLeft2 = bin(intLeft2)
intRight2 = intVal0 >> 2
binValRight2 = bin(intRight2)
print "%11s %4s, %12s"%("Orig Value:", intVal0, binVal0)
print "%11s %4s, %12s"%("val << 1 :", intLeft1, binValLeft1)
print "%11s %4s, %12s"%("val << 2 :", intLeft2, binValLeft2)
print "%11s %4s, %12s"%("val >> 1 :", intRight1, binValRight1)
print "%11s %4s, %12s"%("val >> 2 :", intRight2, binValRight2)
}}}
{{{
Orig Value: 130, 0b10000010
val << 1 : 260, 0b100000100
val << 2 : 520, 0b1000001000
val >> 1 : 65, 0b1000001
val >> 2 : 32, 0b100000
}}}
!!!Inversion \ 'not' examples, {{{~}}}
As mentioned above, this operations yields -(num + 1).
{{{
intVal0 = 130
binVal0 = bin(intVal0)
intNot1 = ~intVal0
binNot1 = bin(intNot1 )
print "%11s %4s, %12s"%("Orig Value:", intVal0, binVal0)
print "%11s %4s, %12s"%("~Value:", intNot1, binNot1)
}}}
{{{
Orig Value: 130, 0b10000010
~Value: -131, -0b10000011
}}}
<<gradient horiz #ffffff #ddddff #8888ff >>
The python tiddlywiki blog
*[[2009 08 27]] - PyGame wiki is live!
*[[2009 04 11]] - Visual Guide to Tkinter widgets
*[[2009 04 07]] - Added [[PYGAME]] Category
*[[2009 04 03]] - Added [[WEB]] Category
*[[2008 08 17]] - Added [[EXECUTION]] Category
*[[2008 08 08]] - Added [[VARIABLES]] Category
*[[2008 07 02]] - Some good Python links on 'special methods', and hacks
*[[2008 06 08]] - Blog about my new blog (blog blog blog)
*[[2008 05 19]] - Python tiddlywiki is born!
Solution I came up with. Makes me happy.
https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.cKDTree.html
https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.cKDTree.query.html#scipy.spatial.cKDTree.query
{{{
import numpy as np
from scipy.spatial import KDTree
import time
np.random.seed(42)
# The 'source' 3D points we want to find the closest neighbor points to:
sourcePoints = np.random.uniform(-2, 2, size=(2, 3))
#print("sourcePoints")
#print(sourcePoints)
# 3D sample points to find cloest distance to our sourcePoints:
searchPoints = np.random.uniform(-2, 2, size=(4, 3))
#print("searchPoints")
#print(searchPoints)
# How many closest search points to find per source point?
# Must be =< len(searchPoints)
findClosestNumber = 4
timeStart = time.time()
# Build a kdTree for our sample points, then return the results
# checking them against our sample points:
dist, indexes = KDTree(searchPoints).query(sourcePoints, findClosestNumber)
# If we only query one closest distance, numpy will return an array of scalars,
# not an array of arrays. For consistency, we want it to always return
# an array of arrays.
if findClosestNumber == 1:
dist = [[item] for item in dist]
indexes = [[item] for item in indexes]
timeEnd = time.time()
print ("Closest %s Sample Point Distances for each Check Point:"%findClosestNumber)
print(dist)
print ("Closest %s Sample Point Indexes for each Check Point:"%findClosestNumber)
print(indexes)
for i in range(len(sourcePoints)):
print("For Check Point %s : Position %s"%(i, sourcePoints[i]))
print(" Closest %s sample Point Indices in order: %s"%(findClosestNumber, indexes[i]))
print(" Distances to each sample point in closest order: %s"%dist[i])
print(" Closest Index / Distance / Sample Point Position : %s / %.4f / %s"%(indexes[i][0], dist[i][0], searchPoints[indexes[i][0]]))
calcDist = np.linalg.norm(sourcePoints[i]-searchPoints[indexes[i][0]])
print(" Confirm The Dist %.4f is equal to the 'mathed distance between points': %.4f : %s"%(dist[i][0], calcDist, dist[i][0]==calcDist))
print("Completed in %.4f seconds"%(timeEnd-timeStart))
}}}
{{{
Closest 4 Sample Point Distances for each Check Point:
[[1.41093283 2.8210816 4.06544334 4.11350663]
[0.96742329 2.2991875 3.32931709 3.98934005]]
Closest 4 Sample Point Indexes for each Check Point:
[[0 3 1 2]
[2 3 1 0]]
For Check Point 0 : Position [-0.50183952 1.80285723 0.92797577]
Closest 4 sample Point Indices in order: [0 3 1 2]
Distances to each sample point in closest order: [1.41093283 2.8210816 4.06544334 4.11350663]
Closest Index / Distance / Sample Point Position : 0 / 1.4109 / [-1.76766555 1.46470458 0.40446005]
Confirm The Dist 1.4109 is equal to the 'mathed distance between points': 1.4109 : True
For Check Point 1 : Position [ 0.39463394 -1.37592544 -1.37602192]
Closest 4 sample Point Indices in order: [2 3 1 0]
Distances to each sample point in closest order: [0.96742329 2.2991875 3.32931709 3.98934005]
Closest Index / Distance / Sample Point Position : 2 / 0.9674 / [ 1.32977056 -1.15064356 -1.27270013]
Confirm The Dist 0.9674 is equal to the 'mathed distance between points': 0.9674 : True
Completed in 0.0000 seconds
}}}
Simple function to calculate weight based on length change: Needed a way to figure out how much a scale model of a larger vehicle would weigh. Given the original vehicles length and weight, by passing in the new length, the function will return the new weight.
{{{
def calcWeight(realLength, realWeight, newLength):
scaleFactor = float(realLength) / float(newLength)
return float(realWeight) / pow(scaleFactor, 3)
}}}
When you shrink a 2d image by half, it's 2d area shrinks by a factor of 4 (square root).
When you shrink a 3d volume by half, it's 3d volume shrinks by a factor of 8 (cube root).
Say you have 3d mesh, like a necklace, that is like a large torus, with multiple cross-sections defining how smooth it is.
If you pass in the list of each of those verts 3d worldspace positions, it will return back a list of sublists, where each sublist is a grouping of vert indices that define a given subdivision.
You can use the minDistMult to help it grab more / less verts for the groupings.
{{{
import numpy as np
from scipy.spatial import KDTree
from scipy.cluster.hierarchy import fclusterdata
def getVertGroups(sourcePoints, minDistMult=4.0):
sourcePoints = np.array(sourcePoints)
dists, indexes = KDTree(sourcePoints).query(sourcePoints, 2)
# item 0 is itself, so a dist of 0, so look to index[1] for a valid distance:
distances = sum([item[1] for item in dists])/len(dists) * minDistMult
clusters = fclusterdata(sourcePoints, distances, criterion="distance", method="average")
data = {}
for i,cIndex in enumerate(clusters):
if cIndex not in data:
data[cIndex] = []
data[cIndex].append(i)
ret = []
for key in data:
ret.append(data[key])
return ret
}}}
* https://docs.scipy.org/doc/scipy/reference/generated/scipy.cluster.hierarchy.fclusterdata.html
* https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.KDTree.html
In this example, we create a subclass, and override a method.
High level differences between Python 2 & 3, see here: [[Initializing a superclass with super()]]
{{{
# Example from a PySide window I was working on, where I wanted to return custom icons based
# on a set of rules.
class IconProvider(QtGui.QFileIconProvider):
def __init__(self):
#super(IconProvider, self).__init__() # Python 2
super().__init__() # Python 3
def icon(self, data):
# This is the method we're overriding...
ret = None
if myLogicGoesHere:
ret = some special icon
if not ret:
# If no match, call to the superclass:
#ret = super(IconProvider, self).icon(data) # Python 2
ret = super().icon(data) # Python 3
return ret
}}}
Or, if you want to 'append' to the method, and not overwrite it:
{{{
class MySubClass(MySuperClass):
def __init__(self):
#super(MySubClass, self).__init__() # Python 2
super().__init__() # Python 3
def someMethod(self, data):
# Run the superclass method:
#super(MySubClass, self).someMethod() # Python 2
super().someMethod() # Python 3
# Now put the code you want to 'append' to it here:
#...........
}}}
----
Older method:
If you have a subclass that overrides a superclass's method, how can you still call to the superclass method through the subclass?
You can call to the superclass method directly, passing in the child class object as the first argument ({{{self}}}).
{{{
class Parent(object):
def __init__(self):
self.value = 0
def doIt(self):
self.value = 23
class Child(Parent):
def __init__(self):
super(Child, self).__init__()
def doIt(self):
self.value = 100
spam = Child()
print spam.value
spam.doIt()
print spam.value
Parent.doIt(spam)
print spam.value
}}}
prints:
{{{
0
100
23
}}}
*When {{{spam}}} is first created through the {{{Child}}} class, {{{value}}} is set to 0, as defined by the superclass {{{Parent.__init__()}}}.
*When the {{{spam.doIt()}}} is called (through the {{{Child}}} class), it sets {{{value}}} to 100.
*But then the superclass {{{Parent.doIt()}}} method is called on {{{spam}}}, setting {{{value}}} to 23.
Sho'nuff:
{{{
def foo(arg):
print arg
def goo(something):
something("yes!")
goo(foo)
# yes!
}}}
In the above example, we define a simple function {{{foo()}}} that takes a single argument, and prints it. The function {{{goo()}}} has an argument, presumed to be some anonymous function, and then passes a single arg into it for execution.
This is a really simple example, but in practice, it allows you to have a single master wrapper function plug arguments into arbitrary anonymous functions passed into it.
While you can do simple command-line argument parsing via [[sys.argv|If runing a script from the comand line, how can I query the arguments the user has passed?]], a more robust solution is via the [[argparse module|http://docs.python.org/2/library/argparse.html]].
Below is a simple example showing how to set it up, and passing in both positional and optional arguments. I wrote this based on how I code, it seems somewhat different than the [[examples|http://docs.python.org/2/howto/argparse.html]] they provide. But hey, it works the way I want ;)
{{{
# spam.py
import argparse
def main(intArg, floatArg, otherArg=None):
print intArg
print floatArg
print otherArg
# When executed from the commandline:
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Do stuff with things!')
parser.add_argument('intArg', type=int,
help='this is intArg')
parser.add_argument('floatArg', type=float,
help='this is floatArg')
parser.add_argument('-oa', '--otherArg', default=None, metavar='someData',
help='this is otherArg')
args = parser.parse_args()
main(args.intArg, args.floatArg, otherArg=args.otherArg)
}}}
Notes:
*To specify an optional argument you use a single-dash ({{{-}}}) for the short-name, and a double-dash ({{{--}}}) for the long name.
*For optional arguments you can also provide (but it's not required) a {{{metavar}}} value, that provides extra info when help is printed.
*You can force a data-type via the 'type' option.
*There is so much more stuff... check the docs.
From the command line, query help:
{{{
$ python spam.py -h
usage: scratchpad.py [-h] [-oa someData] intArg floatArg
Do stuff with things!
positional arguments:
intArg this is intArg
floatArg this is floatArg
optional arguments:
-h, --help show this help message and exit
-oa someData, --otherArg someData
this is otherArg
}}}
And execute:
{{{
$ python spam.py 2 3.5 --otherArg eggs
2
3.5
eggs
}}}
{{{
$ python spam.py 2 3.5
2
3.5
None
}}}
Recently ran into the need to launch Python from a shell and pass in certain arguments to it. Simple example:
{{{
>python - arg1 arg2 arg3
Python 2.6.2 (r262:71605, Apr 14 2009, 22:40:02) [MSC v.1500 32 bit (Intel)] on
win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> print sys.argv
['-', 'argA', 'argB', 'argC']
}}}
Python can obviously take a variety of flags when executed via command line ({{{>python -h}}}). Passing it the 'minus' character '{{{-}}}' tells {{{sys.argv}}} to collect all args passed in after it. So the args are {{{sys.argv[1:]}}}.
Credit goes to [[this blog post|http://www.chrisevans3d.com/pub_blog/?p=494]] by Christopher Evans.
Via the UI, it's pretty easy to 'drag and drop' one or more file's onto a Python module's, and capture the name(s) of the dropped file(s):
{{{
# droptest.py
import sys
def main(data):
f = open('c:\\droptest.txt', 'w')
for d in data:
f.write('%s\n'%d)
f.close()
if __name__ == "__main__":
# Capture the dropped file info:
main(sys.argv[1:])
}}}
Now, you can drag a file onto the icon for {{{droptest.py}}}, and it will update the {{{droptest.txt}}} file with the full path-name of the dropped file. Pretty slick!
{{{sys.argv}}} is a list of items:
*index0: name of the module being executed
*index1->n : All arguments passed into the module. In this case, it will be all the filenames dropped on the module's icon.
{{{
print '%s%s%s'%('A'.ljust(8,'.'), '<-->'.center(8,'.'), 'B'.rjust(8,'.'))
print '%s%s%s'%('aaaa'.ljust(8,'.'), '<-->'.center(8,'.'), 'bbbb'.rjust(8,'.'))
print '%s%s%s'%('aaaaaaaaa'.ljust(8,'.'), '<-->'.center(8,'.'), 'bbbbbbbbb'.rjust(8,'.'))
}}}
{{{
A.........<-->.........B
aaaa......<-->......bbbb
aaaaaaaaa..<-->..bbbbbbbbb
}}}
Notes from Python's [[Built In Functions|http://docs.python.org/library/functions.html#built-in-functions]], and other places around the web...
!Numbers:
[[Convert an integer number to a binary string|http://docs.python.org/library/functions.html#bin]]:
{{{
bin(x)
}}}
----
[[Create a complex number with the value real + imag*j or convert a string or number to a complex number|http://docs.python.org/library/functions.html#complex]]:
{{{
complex([real[, imag]])
}}}
----
[[Convert a string or a number to floating point|http://docs.python.org/library/functions.html#float]]:
{{{
float([x])
}}}
----
[[Convert an integer number (of any size) to a hexadecimal string|http://docs.python.org/library/functions.html#hex]]:
{{{
hex(x)
}}}
----
[[Convert a string or number to a plain integer|http://docs.python.org/library/functions.html#int]]:
The base parameter gives the base for the conversion (which is 10 by default) and may be any integer in the range [2, 36], or zero.
{{{
int([x[, base]])
}}}
----
[[Convert an integer number (of any size) to an octal string|http://docs.python.org/library/functions.html#oct]]:
{{{
oct(x)
}}}
----
[[Given a string of length one, return an integer representing the Unicode code point of the character|http://docs.python.org/library/functions.html#ord]]
This is the inverse of chr() for 8-bit strings and of unichr() for unicode objects.
{{{
ord(c)
}}}
----
Based on code given in a talk [[HERE|http://python.mirocommunity.org/video/1591/pycon-2010-the-mighty-dictiona]] by Brandon Craig Rhodes:
Given an integer, return the value in 32-bit binary notation:
{{{
def bits(n):
n += 2**32
return bin(n)[-32:] # remove '0b'
}}}
{{{
print bits(56)
00000000000000000000000000111000
}}}
!Numric conversion methods:
[[Integer|http://docs.python.org/library/stdtypes.html#additional-methods-on-integer-types]]:
Return the number of bits necessary to represent an integer in binary, excluding the sign and leading zeros:
{{{
int.bit_length()
long.bit_length()
}}}
----
[[Float|http://docs.python.org/library/stdtypes.html#additional-methods-on-float]]:
Return a pair of integers whose ratio is exactly equal to the original float and with a positive denominator:
{{{
float.as_integer_ratio()
}}}
Return a representation of a floating-point number as a hexadecimal string:
{{{
float.hex()
}}}
Class method to return the float represented by a hexadecimal string s:
{{{
float.fromhex(s)
}}}
!Characters:
This is for Python2, need to update for Python 3. See [[bytes and strings]]
[[Return a string of one character whose ASCII code is the integer i|http://docs.python.org/library/functions.html#chr]]:
{{{
chr(i)
}}}
----
[[Return a string containing a nicely printable representation of an object|Return a string containing a nicely printable representation of an object.]]:
{{{
str([object])
}}}
----
[[Return the Unicode string of one character whose Unicode code is the integer i|http://docs.python.org/library/functions.html#unichr]]:
{{{
unichr(i)
}}}
----
[[Return the Unicode string version of object|http://docs.python.org/library/functions.html#unicode]]:
{{{
unicode([object[, encoding[, errors]]])
}}}
For the ~CircuitPython Express, that uses a ~ATSAMD21 ARM Cortex M0 Processor ( running at 3.3V and 48MHz), they have this nice pinout diagram showing what microcontroller pins related to the hardware (board) pins:
http://circuitpython.readthedocs.io/en/stable/atmel-samd/README.html
The "Datasheet" colume with the "PA" and "PB" pins can be gathered by the REPL editor via the {{{microcontroller}}} module:
{{{
import microcontroller
for d in dir(microcontroller.pin):
print(d)
}}}
And you'll get that list.
For all the values it references in red, they're part of the {{{board}}} module.
I have a list of them here: [[CircuitPython : board module attributes]]
But they are gathered a similar way:
{{{
import board
for d in sorted(dir(board)):
print d
}}}
Overview of what's in the 'Adafruit ~CircuitPython Bundle' bundle, since I don't know what all those letters and numbers mean.
https://github.com/adafruit/Adafruit_CircuitPython_Bundle
https://github.com/adafruit/Adafruit_CircuitPython_Bundle/releases
----
{{{/lib}}}
* {{{neopixel}}} : Adafruit Neopixel driver library
** [[CircuitPython : Using the neopixel module/bundle]]
** https://learn.adafruit.com/adafruit-neopixel-uberguide
** http://circuitpython.readthedocs.io/en/stable/docs/esp8266/tutorial/neopixel.html
* {{{dotstar}}} : Adafruit Dotstart driver library
** https://learn.adafruit.com/adafruit-dotstar-leds/overview
* {{{adafruit_thermistor}}} : Used for reading the temp sensor on the CPE.
** http://circuitpython.readthedocs.io/projects/thermistor/en/latest/README.html
* {{{adafruit_si7021}}} : Driver for Adafruit's Si7021 humidity / temp sensor breakout
** https://www.adafruit.com/product/3251
** https://github.com/adafruit/Adafruit_CircuitPython_SI7021
* {{{adafruit_sdcard}}} : ~CircuitPython driver for SD cards using SPI bus.
** http://circuitpython.readthedocs.io/projects/sdcard/en/latest/api.html
** https://github.com/adafruit/Adafruit_CircuitPython_SD
* {{{adafruit_rtttl}}} : Play RTTTL tunes in ~CircuitPython
** https://github.com/adafruit/Adafruit_CircuitPython_RTTTL
* {{{adafruit_pcf8523}}} : This library supports the use of the PCF8523-based RTC (Real Time Clock)
** http://circuitpython.readthedocs.io/projects/pcf8523/en/latest/api.html
* {{{adafruit_mcp9808}}} : The Adafruit MCP9808 Precision I2C Temperature sensor library
** https://github.com/adafruit/Adafruit_CircuitPython_MCP9808
* {{{adafruit_max31855}}} : Library for the Adafruit Thermocouple breakout
** https://github.com/adafruit/Adafruit_CircuitPython_MAX31855
* {{{adafruit_is31fl3731}}} : Library for IS31FL3731 LED charlieplex driver
** https://github.com/adafruit/Adafruit_CircuitPython_IS31FL3731
*{{{adafruit_ds3231}}} : drivers for the DS3231 realtime clock
** https://github.com/adafruit/Adafruit_CircuitPython_DS3231
* {{{adafruit_bno055}}} : Unified sensor driver for the Adafruit ~BNO055 orientation sensor breakout
** https://github.com/adafruit/Adafruit_CircuitPython_BNO055
* {{{/adafruit_waveform}}} : library to generate single wavelength waveforms
** https://github.com/adafruit/Adafruit_CircuitPython_Waveform
* {{{/adafruit_ssd1306}}} : Library to use SSD1306-based 128x64 or 128x32 pixel OLED displays
** https://github.com/adafruit/Adafruit_CircuitPython_SSD1306
* {{{/adafruit_rgb_display}}} : Drivers for RGB displays
** https://github.com/adafruit/Adafruit_CircuitPython_RGB_Display
* {{{/adafruit_register}}} : Python data descriptor classes to represent hardware registers on I2C and SPI devices.
** https://github.com/adafruit/Adafruit_CircuitPython_Register
* {{{/adafruit_pca9685}}} : Python code to use the PCA9685 PWM servo/LED controller
** https://github.com/adafruit/micropython-adafruit-pca9685
* {{{/adafruit_mpr121}}} : Adafruit CircuitPython module for the MPR121 capacitive touch breakout board.
** https://github.com/adafruit/Adafruit_CircuitPython_MPR121
** https://learn.adafruit.com/circuitpython-hardware-mpr121-capacitive-touch-breakout/overview
* {{{/adafruit_lis3dh}}} : Adafruit CircuitPython module for the LIS3DH accelerometer.
** https://github.com/adafruit/Adafruit_CircuitPython_LIS3DH
** https://learn.adafruit.com/circuitpython-hardware-lis3dh-accelerometer/overview
* {{{/adafruit_ht16k33}}}} : Adafruit CircuitPython driver for the HT16K33, a LED matrix driver IC.
** https://github.com/adafruit/Adafruit_CircuitPython_HT16K33
* {{{/adafruit_hid}}} : USB Human Interface Device drivers.
** https://github.com/adafruit/Adafruit_CircuitPython_HID
** http://adafruit-circuitpython-hid.readthedocs.io/en/latest/
* {{{/adafruit_circuitplayground}}} : Example of accessing sensors on the CPE
** http://circuitpython.readthedocs.io/projects/circuitplayground/en/stable/adafruit_circuitplayground/index.html
** http://circuitpython.readthedocs.io/projects/circuitplayground/en/stable/_modules/adafruit_circuitplayground/express.html
* {{{/adafruit_bus_device}}} : Two helper classes that handle transaction related state for I2C and SPI including locks.
** https://github.com/adafruit/Adafruit_CircuitPython_BusDevice
** http://circuitpython.readthedocs.io/projects/bus_device/en/latest/README.html
These docs are based around my work with Adafruit's [[Circuit Playground Express|https://www.adafruit.com/product/3333]] with a host PC running Window 10.
* Press the reset button //once// (not twice, which will enter bootloader mode): After 'a while' (10-30 seconds), it should open a Windows Explorer: There should be a {{{CIRCUITPY}}} drive, mine is consistently {{{E:}}}.
* Code and needed modules (called bundles) can be copied to that drive.
* There are special module names that have meaning to the ~CircuitPython executible:
** {{{boot.py}}} (or {{{settings.py}}}) runs only once on start up before USB is initialized. This lays the ground work for configuring USB at startup rather than it being fixed. Since serial is not available, output is written to boot_out.txt.
*** This module can be omitted.
** {{{code.py}}} (or {{{main.py}}}) is run after every reload until it finishes or is interrupted. After its done the vm and hardware is reinitialized. This means you cannot read state from code.py in the REPL anymore.
** After {{{code.py}}} the REPL can be entered by pressing any key.
So: Any module you wish to execute must be named {{{code.py}}} (or {{{main.py}}}). Optionally, you can have a {{{boot.py}}} (or {{{settings.py}}}) on-board to define additional startup stuff.
For all my testing, I've used an Adafruit [[Circuit Playground Express|https://www.adafruit.com/product/3333]]
Have a first-time setup guide for that microcontroller on my blog, [[here|http://www.akeric.com/blog/?p=4294]]
~CircuitPython is based on [[MicroPython|https://www.micropython.org/]], with [[these differences|https://github.com/adafruit/circuitpython#differences-from-micropython]]
!Links
* Main Aadafruit Github Page for ~CircuitPython: https://github.com/adafruit/circuitpython
** Latest Releases: https://github.com/adafruit/circuitpython/releases
*** Files that end with .bin can be flashed with {{{esptool.py}}} or {{{bossac}}}. Files ending in {{{.uf2}}} can be flashed onto a virtual drive when in bootloader mode.
** Example modules: https://github.com/adafruit/circuitpython/tree/master/examples
*Adafruit ~CircuitPyhon Bundles: https://github.com/adafruit/Adafruit_CircuitPython_Bundle
** Latest Releases: https://github.com/adafruit/Adafruit_CircuitPython_Bundle/releases
** Bundles are .mpy (I'm guessing that stands for "~MicroPYthon") files that can be individually copied to your microcontroller, for use in module imports.
* Forum:
** [[Adafruit CircuitPython and MicroPython|https://forums.adafruit.com/viewforum.php?f=60]]
* Docs:
** Adafruit ~CircuitPython API Reference: http://circuitpython.readthedocs.io/en/latest/
** [[Adafruit MicroPython tutorial for ES2866|http://circuitpython.readthedocs.io/en/stable/docs/esp8266/tutorial/index.html]] : It's neither specifically for ~CircuitPython, nor is it for the CPE, but, there's still a bunch of good examples in there.
** Drivers and Sensors: http://circuitpython.readthedocs.io/en/latest/docs/drivers.html#drivers
** For the ~SAMD21x18 (chip on the CPE and other boards), great matrix showing how each pin is used:
*** http://circuitpython.readthedocs.io/en/stable/atmel-samd/README.html
** Adafruit's {{{adafruit_circuitplayground.express}}} module/bundle: Great place to read code that interfaces with the board.
*** API : http://circuitpython.readthedocs.io/projects/circuitplayground/en/stable/adafruit_circuitplayground/index.html
*** Source Code: http://circuitpython.readthedocs.io/projects/circuitplayground/en/stable/_modules/adafruit_circuitplayground/express.html
*** Example usage:
{{{
from adafruit_circuitplayground.express import circuit
while True:
if circuit.button_a:
print("Temperature:", circuit.temperature)
circuit.red_led = circuit.button_b
}}}
!Installing On Hardware
* Adafruit has a great tutorial [[here|https://learn.adafruit.com/adafruit-metro-m0-express-designed-for-circuitpython/circuitpython]] on getting ~CircuitPython installed on your microcontroller that supports it.
* But in a nutshell:
* Download the {{{.uf2}}} from the releases page.
* Put your microcontroller into bootloader mode: Double-press the reset button, wait for Windows Explorer to open.
* Drag the {{{.uf2}}} onto the microcontrollers drive via Explorer.
* Wait a few minutes: It should be installed.
!REPL Editor
* Adafruit has a great doc [[here|https://learn.adafruit.com/micropython-basics-how-to-load-micropython-on-a-board/serial-terminal]]
This is based around Adafruit's [[Circuit Playground Express|https://www.adafruit.com/product/3333]].
Good overview of the sensors for the CPE can be found here: [[Sensors in MakeCode|https://learn.adafruit.com/sensors-in-makecode]]
Multipurpose doc: [[CircuitPython Basics : Analog Inputs and Outputs|https://learn.adafruit.com/circuitpython-basics-analog-inputs-and-outputs/analog-signals]]
Related wiki subjects:
* [[CircuitPython : board module attributes]]
* [[CircuitPython : analogio module]]
* [[CircuitPython : digitalio module]]
API Reference
* [[analogio.AnalogIn|http://circuitpython.readthedocs.io/en/latest/shared-bindings/analogio/AnalogIn.html]]
* [[digitalio.DigitalInOut|http://circuitpython.readthedocs.io/en/latest/shared-bindings/digitalio/DigitalInOut.html]]
* [[touchio.TouchIn|http://circuitpython.readthedocs.io/en/latest/shared-bindings/touchio/TouchIn.html]]
* [[pluseio.PluseIn|http://circuitpython.readthedocs.io/en/latest/shared-bindings/pulseio/PulseIn.html]]
* [[busio|http://circuitpython.readthedocs.io/en/latest/shared-bindings/busio/__init__.html]]
This doc (which I found after authoring all this) also does a good job showing how to access some of the sensors:
* http://circuitpython.readthedocs.io/projects/circuitplayground/en/stable/_modules/adafruit_circuitplayground/express.html
To use it, presuming you have the bundle installed (from [[these docs|http://circuitpython.readthedocs.io/projects/circuitplayground/en/stable/README.html#usage-example]])
{{{
from adafruit_circuitplayground.express import circuit
while True:
if circuit.button_a:
print("Temperature:", circuit.temperature)
circuit.red_led = circuit.button_b
}}}
For all below examples:
{{{
import board
# and any one of these:
import analogio
import digitalio
import touchio
import pluseio
}}}
It should be noted that the range for the {{{analogio.AnalogIn().value}}} property is 0 -> 65535
!Motion Sensor
{{{LIS3DH}}} triple-axis accelerometer with tap detection, free-fall detection.
This requires the {{{adafruit_lis3dh}}} bundle. See this subject for bundle downloads: [[CircuitPython : Overview]]
* Source for https://github.com/adafruit/Adafruit_CircuitPython_LIS3DH
* See this for all the methods and whatnot: https://github.com/adafruit/Adafruit_CircuitPython_LIS3DH/blob/master/adafruit_lis3dh/lis3dh.py
* See some examples here: https://github.com/adafruit/Adafruit_CircuitPython_LIS3DH/tree/master/examples
Below code is a modified snippet from the [[spinner.py example|https://github.com/adafruit/Adafruit_CircuitPython_LIS3DH/blob/master/examples/spinner.py]]
{{{
import busio
import adafruit_lis3dh
i2c = busio.I2C(board.ACCELEROMETER_SCL, board.ACCELEROMETER_SDA)
motionSensor = adafruit_lis3dh.LIS3DH_I2C(i2c, address=25)
# Set the detection range. The default is RANGE_2_G
motionSensor.range = adafruit_lis3dh.RANGE_16_G
print(motionSensor.acceleration)
(-0.4597684, 4.597683, 7.816063)
}}}
For the acceleration info, if holding the CPE flat, with the USB jack facing you (battery plug facing away):
* X - Tip Right (positive) or Left (negative)
* Y - Tip Forward (positive) or Backward (negative)
* Z - Up (higher values) or Down (lower values)
Acceleration at 1g is 9.81m sec/2 : Held on a flat table, the sensor reports for me: (0.0, 0.0, 9.885021), but it does fluctuate a bit.
!Temperature Sensor
A thermistor : Specs?
Pin : {{{A9}}}
{{{
tempSensor = analogio.AnalogIn(board.TEMPERATURE)
print(tempSensor.value)
}}}
In a room roughly 75 deg F : {{{34896}}}
Also, this, which is way more intuitive, using the {{{adafruit_thermistor}}} bundle:
{{{
import adafruit_thermistor
tempSensor = adafruit_thermistor.Thermistor(board.TEMPERATURE, 10000, 10000, 25, 3950)
print tempSensor.temperature
# 28.78906 # in Celcius
tempF = temp.temperature * 1.8 + 32
print(tempF)
# 81.63797
}}}
Links:
* http://circuitpython.readthedocs.io/projects/thermistor/en/latest/README.html
* https://github.com/adafruit/Adafruit_CircuitPython_Thermistor
* https://github.com/adafruit/Adafruit_CircuitPython_Thermistor/blob/master/adafruit_thermistor.py
!Light Sensor
Pin : {{{A8}}}
{{{
lightSensor = analogio.AnalogIn(board.LIGHT)
print(lightSensor.value)
}}}
My hand covering the sensor in a lit room: {{{190}}}
In a lit room: {{{8000}}}
Directly under a ceiling light, seat height: {{{13000}}}
Also this, using the {{{adafruit_circuitplayground.express}}} bundle:
{{{
from adafruit_circuitplayground.express import circuit
print(circuit.light)
# 29 # (not sure the scale)
}}}
!Color Sensor
Need the {{{tcs34725}}} driver:
http://micropython-tcs34725.readthedocs.io/en/latest/
https://github.com/adafruit/micropython-adafruit-tcs34725 <- this?
{{{
}}}
!Sound Sensor
MEMS microphone
Doesn't seem supported on ~CircuitPython 1.0: Looks like the 2.0 release has support for:
https://circuitpython.readthedocs.io/en/latest/shared-bindings/audiobusio/PDMIn.html
{{{
board.MICROPHONE_DO
board.MICROPHONE_SCK
}}}
!Push Buttons
Button A pin: {{{D4}}}
Button B pin: {{{D5}}}
{{{
buttonA = digitalio.DigitalInOut(board.BUTTON_A)
buttonA.switch_to_input(pull=digitalio.Pull.DOWN)
buttonB = digitalio.DigitalInOut(board.BUTTON_B)
buttonB.switch_to_input(pull=digitalio.Pull.DOWN)
print(buttonA.value)
print(buttonB.value)
}}}
!Slide Switch
Button : {{{D7}}}
{{{
slideSwitch = digitalio.DigitalInOut((board.SLIDE_SWITCH)
slideSwitch.switch_to_input(pull=digitalio.Pull.UP)
print(slideSwitch.value)
}}}
!Infrared receiver
"Can receive and transmit any remote control codes, as well as send messages between Circuit Playground Expresses. Can also act as a proximity sensor."
Associated board pins:
{{{
board.IR_PROXIMITY
board.IR_RX
board.IR_TX
}}}
''Proximity Sensor''
Is this the right way to do it? Modified from the docs, while aiming my TV remote at it pressing the power button. It should be noted that it was stuck in the {{{while}}} loop until I started pressing the remote button at it, so it does seem to detect this way?
{{{
pulses = pulseio.PulseIn(board.IR_PROXIMITY)
# Wait for an active pulse
while len(pulses) == 0:
pass
# Pause while we do something with the pulses
pulses.pause()
print(len(pulses))
# 2
print(pulses[0])
# 1915
# Clear the rest
pulses.clear()
# Resume with an 80 microsecond active pulse
pulses.resume(80)
}}}
!Capacitive Touch
Looks like it supports pins {{{A1}}}->{{{A7}}}
{{{
touchpad = touchio.TouchIn(board.A1)
print(touchpad.value)
}}}
If you need to wipe / reflash your board:
* This doc describes the process: https://github.com/adafruit/circuitpython/pull/220/files
** https://github.com/adafruit/Adafruit_SPIFlash/tree/master/examples/flash_erase_express
** https://github.com/adafruit/circuitpython/releases/tag/1.0.0
Downloaded via the Adafruit ~CircuitPython bundle: https://github.com/adafruit/Adafruit_CircuitPython_Bundle/releases
Copy the .mpy file directly to your microcontroller, for module import usage.
There are 10 neopixels on the CPE: index0 is at the 5 o'clock position (by the green "on" LED"), and they count in a counter-clockwise direction.
Neopixels are actually 3 separate RGB leds, that turn on individually.
Docs
*[[NeoPixel Library|https://circuitpython.readthedocs.io/projects/neopixel/en/latest/]]
*[[[neopixel.NeoPixel|https://circuitpython.readthedocs.io/projects/neopixel/en/latest/api.html]] API Reference
*[[Adafruit NeoPixel Uberguide|https://learn.adafruit.com/adafruit-neopixel-uberguide]]
Notes:
* Its now more like a normal Python sequence and features slice support, repr and len support.
* Colors are now stored as ints by default rather than tuples. However, you can still use the tuple syntax to set values. For example, 0x100000 is equivalent to (0x10, 0, 0).
* When setting colors as a tuple, the range is 0-255 : {{{(0,0,0)}}} is black, {{{(255,255,255)}}} is bright white.
* When setting colors, it ''must be a tuple'' : Lists //won't// work. If you have a list, convert it: {{{color = tuple(someListData)}}}.
----
My notes:
{{{
import board
import neopixel
}}}
Create a new neopixel instance for all pixels on the board:
{{{
# If auto_write is True, pixels will change color as soon as you set them.
# if False, then you need to call to the show() method to update them
pixels = neopixel.NeoPixel(board.NEOPIXEL, 10, auto_write=False)
# you can turn auto_write back on at any time:
pixels.auto_write = True
}}}
Turn all neopixels off with the {{{fill}}} method:
{{{
pixels.fill((0,0,0))
}}}
Or turn them all on bright green:
{{{
pixels.fill((0,255,0))
}}}
Pixels can be individually set, the {{{pixels}}} instance acts like a sequence:
{{{
pixels[0] = (128,128,0)
}}}
This will set them all to a random color/brightness:
{{{
import urandom
for i in range(10):
randCol = tuple([urandom.randrange(255) for j in range(3)])
pixels[i] = randCol
}}}
Take control of the overall brightness level, values are from 0->1.0
{{{
# Cut brightness in half
pixels.brightness = .5
pixels.show() # need to do this to see the results, even if auto_write = True
}}}
----
Examples pulled from various code:
----
This example demonstrates the library with the ten built-in ~NeoPixels on the Circuit Playground Express. It turns off {{{auto_write}}} so that all pixels are updated at once.
{{{
import board
import neopixel
pixels = neopixel.NeoPixel(board.NEOPIXEL, 10, auto_write=False)
pixels[0] = (10, 0, 0)
pixels[9] = (0, 10, 0)
pixels.show()
}}}
----
For the CPE:
{{{
import neopixel
from board import *
RED = 0x100000 # (0x10, 0, 0) also works
pixels = neopixel.NeoPixel(NEOPIXEL, 10)
for i in range(len(pixels)):
pixels[i] = RED
}}}
----
For the CPE, setting every other pixel red using a slice:
{{{
import neopixel
from board import *
import time
RED = 0x100000 # (0x10, 0, 0) also works
# Using `with` ensures pixels are cleared after we're done.
with neopixel.NeoPixel(NEOPIXEL, 10) as pixels:
pixels[::2] = [RED] * (len(pixels) // 2)
time.sleep(2)
}}}
----
Take from: https://learn.adafruit.com/fidget-spinner-tachometer/arduino?view=all#circuitpython
{{{
import board
import neopixel # .mpy must also live on microcontroller.
# Configure NeoPixels and turn them all off at the start.
pixels = neopixel.NeoPixel(board.NEOPIXEL, 10)
pixels.fill((0,0,0))
pixels.write() # is this needed? Seems to execute immediately.
# Turn all pixels red:
pixels.fill((255,0,0))
pixels.write() # is this needed? Seems to execute immediately.
# Turn certain pixels white:
pixels[0] = (255, 255, 255)
pixels[1] = (255, 255, 255)
pixels[2] = (255, 255, 255)
pixels.write() # is this needed? Seems to execute immediately.
}}}
This is based around Adafruit's [[Circuit Playground Express|https://www.adafruit.com/product/3333]].
Good overview of the sensors for the CPE can be found here: [[Sensors in MakeCode|https://learn.adafruit.com/sensors-in-makecode]]
Multipurpose doc: [[CircuitPython Basics : Analog Inputs and Outputs|https://learn.adafruit.com/circuitpython-basics-analog-inputs-and-outputs/analog-signals]]
Related wiki subjects:
* [[CircuitPython : board module attributes]]
* [[CircuitPython : analogio module]]
* [[CircuitPython : digitalio module]]
API Reference
* [[analogio.AnalogOut|https://circuitpython.readthedocs.io/en/stable/shared-bindings/analogio/AnalogOut.html]]
* [[digitalio.DigitalInOut|http://circuitpython.readthedocs.io/en/latest/shared-bindings/digitalio/DigitalInOut.html]]
* [[audioio.AudioOut|https://circuitpython.readthedocs.io/en/stable/shared-bindings/audioio/AudioOut.html]]
* [[pluseio.PWMOut|https://circuitpython.readthedocs.io/en/stable/shared-bindings/pulseio/PWMOut.html]]
----
For all below examples:
{{{
import board
# and any one of these:
import digitalio
import audioio
import pulseio
}}}
! ~NeoPixels
See: [[CircuitPython : Using the neopixel module/bundle]]
! Speaker
From the [[AudioOut Docs|http://circuitpython.readthedocs.io/en/latest/shared-bindings/audioio/AudioOut.html]].
However, I don't hear anything :(
{{{
import audioio
import board
import array
import time
import math
# Generate one period of sine wav.
length = 8000 // 440
sine_wave = array.array("H", [0] * length)
for i in range(length):
sine_wave[i] = int(math.sin(math.pi * 2 * i / 18) * (2 ** 15) + 2 ** 15)
sample = audioio.AudioOut(board.SPEAKER, sine_wave)
sample.play(loop=True)
time.sleep(1)
sample.stop()
}}}
! Digital Out : LED D13
The little LED on pin D13, by the USB port.
{{{
led = digitalio.DigitalInOut(board.D13)
led.switch_to_output()
led.value = True
}}}
! PWD Out : LED D13
https://learn.adafruit.com/circuitpython-basics-analog-inputs-and-outputs/pulse-width-modulation-outputs
{{{
led = pulseio.PWMOut(board.D14)
# Turn on full bright:
led.duty_cycle = 65535
# Turn on 50%
led.duty_cycle = 32767
# Turn off:
led.duty_cycle = 0
}}}
{{{duty_cycle}}} value is a 16-bit unsigned int, from 0 to 65535.
! DAC Out
https://learn.adafruit.com/circuitpython-basics-analog-inputs-and-outputs/digital-to-analog-converters-outputs
Analog hardware support
https://www.youtube.com/watch?v=0pUBP0k5WD4
The {{{analogio}}} module contains classes to provide access to analog IO typically implemented with digital-to-analog (DAC) and analog-to-digital (ADC) converters.
* [[analogio|http://circuitpython.readthedocs.io/en/latest/shared-bindings/analogio/__init__.html]]
** [[analogio.Analogin|http://circuitpython.readthedocs.io/en/latest/shared-bindings/analogio/AnalogIn.html]]
** [[analogio.Analogout|http://circuitpython.readthedocs.io/en/latest/shared-bindings/analogio/AnalogOut.html]]
{{{
import analogio
from board import *
}}}
{{{
pin = analogio.AnalogIn(A0)
print(pin.value)
pin.deinit()
# Or
with analogio.AnalogIn(A0) as pin:
print(pin.value)
}}}
{{{
from microcontroller import pin
dac = analogio.AnalogOut(pin.PA02) # output on pin PA02
dac.value = 32768 # makes PA02 1.65V
}}}
Even though {{{board}}} [[has docs|http://circuitpython.readthedocs.io/en/latest/shared-bindings/board/__init__.html]], they don't actually //say// anything about it, other than they can vary per board. Not helpful :S
There is a nice grid of them here: http://circuitpython.readthedocs.io/en/stable/atmel-samd/README.html
Showing how they relate to the microcontrollers pinout. Also see: [[CircuitPython: Accessing pintouts]]
For Adafruit's [[Circuit Playground Express|https://www.adafruit.com/product/3333]], via the REPL:
{{{
import board
for d in sorted(dir(board)):
print d
}}}
{{{
A0
A1
A2
A3
A4
A5
A6
A7
A8
A9
ACCELEROMETER_INTERRUPT
ACCELEROMETER_SCL
ACCELEROMETER_SDA
BUTTON_A
BUTTON_B
D13
D4
D5
D7
D8
FLASH_CS
IR_PROXIMITY
IR_RX
IR_TX
LIGHT
MICROPHONE_DO
MICROPHONE_SCK
MISO
MOSI
NEOPIXEL
REMOTEIN
REMOTEOUT
RX
SCK
SCL
SDA
SLIDE_SWITCH
SPEAKER
SPEAKER_ENABLE
TEMPERATURE
TX
}}}
Basic digital pin support
https://www.youtube.com/watch?v=ZJJ4WkPRddc
* [[digitalio|http://circuitpython.readthedocs.io/en/latest/shared-bindings/digitalio/__init__.html]]
** [[DigitialInOut|http://circuitpython.readthedocs.io/en/latest/shared-bindings/digitalio/DigitalInOut.html]] - digital input and output
** [[Direction|http://circuitpython.readthedocs.io/en/latest/shared-bindings/digitalio/Direction.html]] - defines the direction of a digital pin
** [[DriveMode|http://circuitpython.readthedocs.io/en/latest/shared-bindings/digitalio/DriveMode.html]] - defines the drive mode of a digital pin
** [[Pull|http://circuitpython.readthedocs.io/en/latest/shared-bindings/digitalio/Pull.html]] - defines the pull of a digital pin
{{{
import digitalio
from board import *
}}}
{{{
pin = digitalio.DigitalInOut(D13)
print(pin.value)
}}}
{{{
import time
led = digitalio.DigitalInOut(D13)
led.direction = digitalio.Direction.OUTPUT
while True:
led.value = True
time.sleep(0.1)
led.value = False
time.sleep(0.1)
}}}
Object Oriented Programming (OOP) In Python.
Also see [[Class - advanced]] for deeper info on classes.
Here is a pretty good overview:
http://www.pasteur.fr/formation/infobio/python/ch18.html
This is pulled from the 'Programming Course for Biologists at the Pasteur Institute', so the examples are a bit... 'genetics related'. But they have nice pictures, and get the point across.
''Simple Overview:''
*''Class'': AKA, "The Blueprint". A class is an //object// maker: it contains all the statements needed to create an //object//, it's //attributes//, as well as the statements to describe the operations that the //object// will be able to perform, via its //methods//. Think of it as an '//object// factory'. To say it another way: A //class// isn't an //object//, it's a design for one. Consider a //class// as the blueprint for an //object//.
*''Instance'': AKA, "The Process". The process of creating //objects// from a //class// is called //instantiation//. //Classes// make //instances// of themselves, which are //objects//. You create an //instance// by calling to a //function// with the same name as the //class//. This function is called the //constructor method// (see below). You can actually have multiple constructors, allowing for different default arguments to be passed in during //instancing//. This is called "overloading the constructor".
*''Object'': AKA, "The Result". An //object// is a framework to group values and operations on these values. It is an //instance// of a //class//. When a //class// goes to work, an //object// is the result (via instantiation).
*''Method'': AKA, "An Ability". A //method// is a [[function|Function]] defined for a //class//, specifying a behavior of the //class instances//. Method definitions follow exactly the same pattern as standard [[function|Function]] definitions, except that they must have declared a first argument (called {{{self}}}, see below) for referring to the //instance// they belong too. A method gives an object the ability to do something.
*''Attribute'': AKA, "A Memory". //Attributes// are variables that live inside of an //object//, as defined by the //class//. They can be filled with values when the //instance// is made, as defined by the //constructor function//. Basically, //attributes// let objects remember things, and act on them via their //methods//.
Simple data breakdown:
*''Class'' - Makes (via instancing):
**''Objects'' - Instance of a class, which contain (based on the class definitions):
***''Methods'' - (functions defined inside of the class)
***''Attributes'' - (variables defined inside of the class)
A simple class:
{{{
class Foo(object): # 1 - Python 2 : Python 3 can omit the '(object)' entirely.
def __init__(self, namer, num): # 2
self.name = namer # 3
self.number = num # 4
def bar(self): #5
print self.name + "_" + str(self.number) #6
def incNum(self): #7
self.number = self.number + 1 #8
print self.number #9
}}}
Now build an object, and see what it does:
{{{
>>> myObject = Foo("doof", 3) #10
>>> myObject.incNum() # 11
4 #12
>>> myClass.bar() #13
doof_4 #14
}}}
What exactly is going on here?
#Define the class name. __Class names are ''C''apitalized__. By specifying {{{(object)}}}, this is defined as a //new style class// (a good thing, do it).
#{{{__init__}}} is the //constructor method// (also called the 'initialization method') that is called when a new object is created, via //class instantiation//. This method is called to in #10. {{{namer}}} & {{{num}}} are //arguments// used to pass in creation data, usually used in the following listed //attributes// (lines #3 & #4). Default argument values are also supported: {{{namer = "geewiz"}}} would also be acceptable.
#Create an __attribute__ called {{{.name}}}. Fill it with the value the user passes in through the //argument// {{{namer}}}: the string {{{"doof"}}} from #10. FYI, the //argument// and the //attribute// can have the same name, but I made them different here to make how the data flows more visual.
#Create an __attribute__ called {{{.number}}}. Fill it with the value the user passes in through the //argument// {{{num}}}: The int {{{3}}} from #10.
#Define a __method__ for this class called {{{bar}}}. After an object is created, methods can be called to via '//dot notation//', as seen in #11 & #13.
#This method simply prints the value of the //attribute// {{{.name}}}, adds an string underscore {{{_}}}, and then adds the current value of the attribute {{{.number}}} to the end. (#14)
#Define another __method__ for this class called {{{incNum}}}.
#Take the current value of the //attribute// {{{.number}}}, and increment it by 1.
#Print the current value of the //attribute// {{{.number}}} (#12).
#Create an //instance// of our {{{Foo}}} //class//, as //object// {{{myObject}}}. Pass in the string {{{"doof"}}} as the //argument// {{{namer}}} to the //constructor method// (#2). Also pass in the int {{{3}}} to the //argument// {{{num}}}.
#Call to the {{{incNum}}} method on our {{{myObject}}} //object//. This will add 1 to the current //attribute value//.
#The {{{incNum}}} method's {{{print}}} command (#9) prints out the current //attribute value//
#Call to the {{{bar}}} method on our {{{myObject}}} //object//. This concatenates the strings and ints together, and prints them out (#6).
#The value printed from the {{{bar}}} method.
----
''Want to know more about '[[self|What is up with 'self'?]]'?''
----
From the link at the top, here is another simple class example. The user can define the starting position on a xy plane, and via it's methods, move it around, and 'show' where it is at:
{{{
class Point(object):
"""This is a docstring, use them"""
def __init__(self, x, y):
self.xy = (x, y)
def show(self):
print self.xy
def move(self, mx, my):
self.xy = (self.xy[0]+mx, self.xy[1]+my)
p = Point(1, 2)
}}}
For a more basic overview of classes, please see [[Class]].
Good Class Authoring (from "Python Programming For The Absolute Beginner"):
*When you write a class:
**Create methods so that clients (users) won't need to directly access an object's attributes.
**Use privacy sparingly and only for those few attributes and methods that are completely internal to the operation of objects.
*When you use an object:
**Minimize the direct reading of an object's attributes.
**Avoid directly altering an object's attributes.
**Never directly access an object's private attributes or methods.
----
''List of topics'':
*[[Class Attributes]]
*[[Static Methods]]
*[[Private Attributes]]
*[[Private Methods]]
*[[Get and set methods]]
*[[Properties|property]]
*[[Class Inheritance]]
*[[Method Overriding]]
*[[Emulating Numeric Types \ Operator Overloading|How can I have objects add themselves together? Subtract one another, etc?]]
''Class Attributes'':
Any variable assigned //outside// of a method creates a 'class attribute'.
{{{
# let's make a class attribute:
class SomeClass(object):
classAttrA = 0
def __init__(self):
SomeClass.classAttrA += 1
# etc, furthermore, and so-on...
}}}
{{{classAttrA}}} is now available to all instances of the class. Meaning, any object created via the class will see the same variable data. Getting the class attribute value, whether in a method, or outside the class completely, is done by accessing the //class// directly:
{{{
classAttrVal = SomeClass.classAttrA
}}}
The assignment statement is only executed once, when Python first sees the class definition. This means that the class attribute exists even before a single object is created: You can use a class attribute without any objects of the class in existence. As see in the above example, an object's method can modify a class attribute. They can also be modified through the class directly, outside of any object.method:
{{{
SomeClass.classAttrA = 10
}}}
This would fail:
{{{
sc = SomeClass()
sc.classAttrA = 10
}}}
It won't give an exception, but neither will it actually update the class attribute.
When one class inherits another, it automatically gets (or inherits) all of the methods and attributes of the current class. Example:
{{{
# make our base class:
class Foo(object):
def __init__(self, val):
self.val = val
def someMethod():
self.attr = self.attr * 10
# make our derived class that inherits Foo:
class NewFoo(Foo):
def someNewFooMethod():
self.newFooAttr = self.attr * .1
}}}
{{{class NewFoo}}} inherits all of the methods from {{{Foo}}} ({{{__init__}}} & {{{someMethod}}}), plus, can create new ones ({{{someNewFooMethod}}}). {{{NewFoo}}} is considerfed a //derived class//, since it derives part of its definition from {{{Foo}}}. {{{Foo}}} is considered a //base class// (or //superclass//), because {{{NewFoo}}} is based on it.
Here is another example. In it, we have a superclass {{{Foo}}} that takes arguments. We build a subclass {{{Goo}}} that calls too it, but passes arguments through in a special way:
{{{
class Foo(object):
def __init__(self, goo = "gOo", num = 45):
self.goo = goo
self.num = num
class Noo(Foo):
def __init__(self, snarg = "snarg!", **kwargs):
Foo.__init__(self, **kwargs)
self.snarg = snarg
n = Noo(goo = "goo!", num = 23)
print n.snarg
print n.goo
print n.num
# snarg!
# goo!
# 23
}}}
Rather than having to explicitly type each of the {{{Foo.__init__}}} args into the {{{Noo.__init__}}} definition, we use the 'keyword argument' method ({{{**kwargs}}}) of passing them through. By doing this, it saves us from having to update {{{Noo.__init__}}} with new args every time we decide to add a new arg to {{{Foo.__init__}}}.
http://docs.python.org/library/functions.html#classmethod
Class methods differ from [[Static Methods]] in that they return (or can return) a new object of the type of class (If not returning a class, might as well use a static method). They can be authored using a [[decorator]] {{{@}}}. Rather than having their first argument be {{{self}}}, or a reference to the instance object in question, their first arg is {{{cls}}} (by convention, the name {{{cls}}} is arbitrary, just like {{{self}}}), which is a reference to the //class//.
Example, with a {{{Vect2}}} class. We author a 'makeFromPoints' function as a {{{classmethod}}}. When called to via the class itself, it will return a new {{{Vect2}}} object:
{{{
class Vect2(object):
@classmethod
def makeFromPoints(cls, P1, P2):
# Pass in two sets of points,
# returns the Vector2 object between them.
return cls(P2[0] - P1[0], P2[1] - P1[1])
def __init__(self, x=0.0, y=0.0):
self.x = x
self.y = y
def __str__(self):
return "(%s, %s)" % (self.x, self.y)
}}}
{{{
p1 = [2.0, 1.0]
p2 = [3.0, 1.0]
p3 = Vect2.makeFromPoints(p1, p2)
print p3
# (1.0, 0.0)
}}}
----
Also see:
*[[Static Methods]]
You can setup interactive sliders in colab, to change variable values. Here's an example:
{{{
NUM_IMAGES = 1000 #@param {type:"slider", min:1000, max:10000, step:1000}
}}}
{{{Tkinter}}} is a Python binding to the [[Tcl|http://www.tcl.tk/]] (tool command language) GUI ''t''ool''k''it (Tk).
----
Every widget can use their {{{place}}}, {{{pack}}}, or {{{grid}}} methods depending on which //geometry manager// is being used.
----
''Overview'':
*{{{BitmapImage}}} : Image object for placing bitmap images on other widgets
*{{{Button}}} : a button.
*{{{Canvas}}} : Graphics drawing area: lines, circles, photos, text, etc.
*{{{Checkbutton}}} : a checkbox. Before you can make one, you first need to first create an object based on the {{{BooleanVar}}} class, to store the checkbox value: {{{myCheckVal = BooleanVar()}}}. FYI, the {{{BooleanVar}}} object has a {{{.get()}}} method, for 'getting' it's value. Parameters:
**{{{variable}}} : pointer to the {{{BooleanVar}}} object created beforehand.
*{{{Entry}}} : Single-line text entry field. Methods:
**{{{.get}}} :
**{{{.delete}}} : See the Text.delete method below
*{{{Frame}}} :
*{{{Label}}} : a string of text in a UI.
*{{{LabelFrame}}} : Labled Frame widget
*{{{Listbox}}} : List of selection names
*{{{Menu}}} : Options associated with a {{{Menubutton}}} or top-level window
*{{{Menubutton}}} : Button that opens a Menu of selectable options/submenus
*{{{Message}}} : Multi-line text display field (label)
*{{{OptionMenu}}} : Composite: pull-down selection list.
*{{{PanedWindow}}} : Multipane window interface
*{{{PhotoImage}}} : Image object for placing full-color images on other widgets
*{{{Radiobutton}}} : Like {{{Checkbutton}}}, requires you first make an object to store the value. In this case, it's a {{{StringVar}}} object. {{{StringVar}}} has a {{{.get()}}} method, for getting its value. {{{Radiobutton}}}s are 'grouped' together based on the {{{StringVar}}} they share.
*{{{Scale}}} : A slider widget with scalable position
*{{{Scrollbar}}} : Bar for scrolling other widgets
*{{{ScrolledText}}} : Composite: text with attached scrollbar
*{{{Spinbox}}} : Multiple selection widget
*{{{Text}}} : Multi-line text browse/edit widget. Supports fonts. Methods:
**{{{.get}}} :
**{{{.delete}}} : for example: {{{.delete(0.0, END)}}} : This deletes all text from column 0, row 0, to the end of the text box,
**{{{.insert}}} : Similar style to the {{{.delete}}} method, but the second arg is the name of the string to insert.
*{{{Tk}}} : For making the main window. Also {{{Toplevel}}}. Methods:
**{{{.title}}} : takes a string
**{{{.geometry}}} : Takes a string that is the width and height of the window: {{{.geometry("250x150")}}}
Also see:
*[[UI basics with Tkinter]]
My notes, as a compiler noob.
! Compilers
* [[MSVC|https://en.wikipedia.org/wiki/Microsoft_Visual_C%2B%2B]] : Microsoft Visual C++ : Windows
* [[Xcode|https://en.wikipedia.org/wiki/Xcode]] : Mac
* [[gcc|https://en.wikipedia.org/wiki/GNU_Compiler_Collection]] : The GNU Compiler Collection : Linux
! Figuring out which version of compiler you need
Launching Python gives you the build info, here's some examples:
{{{
Python 2.7.11 (default, Jul 1 2016, 02:08:48) [MSC v.1900 64 bit (AMD64)] on win32
}}}
{{{
Python 2.7.16 (v2.7.16:413a49145e, Mar 4 2019, 01:37:19) [MSC v.1500 64 bit (AMD64)] on win32
}}}
{{{
Python 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 18:41:36) [MSC v.1900 64 bit (AMD64)] on win32
}}}
We can see that it was compiled against 'MSC v.1900', and via the above wiki link, has this info:
{{{
MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015 version 14.0)
}}}
So we know we need to use Visual Studio v 14.0 for the compile.
FYI, on disk, MSVC v14.0 would actually look like:
{{{
\msvc140
}}}
It's 14.0, not '140'.
! Finding compiler version from Python
https://docs.python.org/3/library/platform.html
{{{
import platform
plat = platform.platform(True, True)
# 'Windows-10'
comp = platform.python_compiler()
# 'MSC v.1500 64 bit (AMD64)'
}}}
So, Python comes with a builtin function for this, which I failed to realize:
{{{
print divmod(15, 6)
(2,3)
# 15/6 = 2, remainder 3
}}}
But, my older notes below:
----
{{{
def divMod(val, divisor):
return val//divisor, val%divisor
}}}
{{{
print divMod(15, 6)
(2, 3)
# 15/6 = 2, remainder 3
}}}
{{{//}}} Is 'floor division': Returns the value without remainder.
{{{%}}} is 'modulus' : Returns just the remainder.
----
Both of these are present in Python's [[operator|http://docs.python.org/library/operator.html]] module as well:
{{{
import operator
def divWithRemainder(val, divisor):
return operator.floordiv(val, divisor), operator.mod(val, divisor)
}}}
Constants in Python have variable names in ALL CAPS, and should be authored at the top of the module, after imports, in global scope ([[PEP8|http://www.python.org/dev/peps/pep-0008/]]).
{{{
BOB = "human"
WIDTH = 256
ZERO = 0
}}}
By defining a constant, you're basically telling yourself to //not// change its value. You still can, Python won't stop you, but that would be //bad// based on convention....
When you assign a variable to an object, you're simply pointing that variable to a location in memory (the object in question). If you then pass that variable name as argument to other functions\methods, they all end up referencing the same location in memory. Sometimes this is desired, and sometimes not. If //not//, how can you get //unique// objects in memory, rather than //shared// references?
Build our example classes:
{{{
import copy
class Foo(object):
# simply holds some data, modified by external class
def __init__(self):
self.data = []
class Worker(object):
def __init__(self, foo, work):
self.foo = foo
self.work = work
def update(self):
# update each Foo class with work data
for f in self.foo:
f.data.append(self.work)
def printData(self):
for f in self.foo:
print f.data
}}}
Example #1: Build a list of two {{{Foo}}} objects, pass that list into our two {{{Worker}}} objects, and have each worker objects do some work:
{{{
# -----------------
myList = [Foo(), Foo()]
workerA = Worker(myList, "workerA")
workerB = Worker(myList, "workerB")
workerA.update()
workerA.printData()
#['workerA']
#['workerA']
workerB.update()
workerB.printData()
#['workerA', 'workerB']
#['workerA', 'workerB']
}}}
As you can see, the first object execution of {{{workerA}}} does what is expected. But when you run {{{workerB}}}, it too sees the results from {{{workerA}}}. Why is this? Because both {{{Worker}}} objects are pointing to the same {{{list}}} object ({{{myList}}}), which in turn points to the same {{{Foo}}} objects.
Example #2. We need each list to contain unique {{{Foo}}} objects. That's what {{{copy.deepcopy()}}} does for us:
{{{
# -------
myList = [Foo(), Foo()]
workerA = Worker(copy.deepcopy(myList), "workerA")
workerB = Worker(copy.deepcopy(myList), "workerB")
workerA.update()
workerA.printData()
#['workerA']
#['workerA']
workerB.update()
workerB.printData()
#['workerB']
#['workerB']
}}}
Now, when the {{{Worker}}} objects do their work, the results are saved on unique {{{Foo}}} objects.
Much of this I have learned from others, we all ride on shoulders of giants. But for what I present as my own work, it's under the below licence:
----
All information on this wiki is under the Apache Licence, v 2.0:
{{{
Copyright 2014 Eric Pavey
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
}}}
To understand how this licence works see [[this overview|http://developer.kde.org/documentation/licensing/licenses_summary.html]].
But it pretty much means you can use the information on this wiki however you want, but I always appreciate credit where applicable.
Simple counter class. You can get the current count value by printing it, by accessing the {{{count}}} attribute, or by calling to it will return the value and increment it.
{{{
class Counter(object):
def __init__(self, count=0):
self.count = count
def __str__(self):
return str(self.count)
def __call__(self):
count = self.count
self.count += 1
return count
}}}
{{{
counter = Counter(1)
print counter
print counter.count
print "First the number is %s, then the number is %s, and finally it is %s."%(counter(), counter(), counter())
}}}
{{{
1
1
First the number is 1, then the number is 2, and finally it is 3.
}}}
This blog post:
http://ilab.cs.byu.edu/python/socketmodule.html
And specifically these two links:
*[[Simple Echo Server|http://ilab.cs.byu.edu/python/socket/echoserver.html]]
*[[Simple Echo Client|http://ilab.cs.byu.edu/python/socket/echoclient.html]]
Provide great, simple examples on how to setup a network in Python. If you evaluate the code in two separate shells, you can have the one talk to the other.
Link to Python's {{{socket}}} docs [[here|http://docs.python.org/library/socket.html]]
----
Some more examples on ~GitHub:
https://github.com/rspivak/csdesign
Great reference showing interactive curve easing functions:
http://easings.net/
And the code for it all (~JavaScript) is here:
http://gsgd.co.uk/sandbox/jquery/easing/jquery.easing.1.3.js
Here's some Python conversions:
~JavaScript:
{{{
easeInOutCubic: function (x, t, b, c, d) {
if ((t/=d/2) < 1) return c/2*t*t*t + b;
return c/2*((t-=2)*t*t + 2) + b;
},
easeInQuad: function (x, t, b, c, d) {
return c*(t/=d)*t + b;
},
}}}
Python: (note I left out the 'x', since it isn't needed in these funcs)
{{{
"""
t: current time
b: beginning value
c: change In value
d: duration
"""
def easeInQuad(t, b, c, d):
T = t/d
return c*T*T+b
def easeInOutCubic(t, b, c, d):
T = t / (d / 2)
if T < 1:
return c/2*T*T*T + b
else:
TT = T - 2
return c / 2 * ( TT*TT*TT + 2) + b
}}}
Note with the Python, you can't modify values in-place like they do in ~JavaScript: {{{ if ((t/=d/2) < 1)}}}. While this is legal in Python:
{{{
a = 4
a += 3
}}}
This would fail:
{{{
a = 4
b = a += 3
}}}
Because of that, I broke them out into their own lines, an it works just fine, and is slightly less confusing ;)
When authoring a [[function|Function]] or [[method|Method]] definition, you have the option of creating //parameters//, which accept [[arguments|argument]]. A nice thing about Python is its ability to enable you to author //default arguments//: These are arguments that come with built-in values. Example:
{{{
def foo(param1 = "arg1", param2 = "arg2"):
print param1
print param2
>> foo()
param1
param2
}}}
In the above example, the parameters had default default arguments, so the user did not need to input any. They could if they wanted to of course:
{{{
>> foo(1,2)
1
2
}}}
You can also mix up which parameters have default arguments. FYI, if any parameters //won't// have default arguments, they need to be listed //first//.
{{{
def foo(param1, param2 = "arg2"):
print arg1
print arg2
>> foo(1)
1
arg2
}}}
Since no default argument was provided for the first parameter in the function signature, I had to provide one. If I had just executed {{{foo()}}}, I would have got a {{{TypeError}}}.
----
Python provides ways to find these default values. Based on [[this link|http://docs.python.org/reference/datamodel.html#the-standard-type-hierarchy]] under 'Callable Types -> User-defined functions -> Special attributes' they have a table showing built in function object attrs that can be queried. Specifically an attribute called {{{func_defaults}}}:
{{{
def func(a,b=2):
c=3
cnuf= func
print cnuf.func_defaults
(2,)
}}}
I'm always surprised that the Perfoce ui doesn't give the user the option to delete all empty changelists. Here's a simple function that will do it via the P4 API. See [[Perforce access via Python]].
{{{
import P4
def deleteEmptyChangelists():
p4 = P4.P4()
# User needs to handle p4.errors & p4.warnings (not done in this code):
p4.exception_level = 0
p4.connect()
# Get all current changes for this client:
data = p4.run("changes", "-s", "pending", "-c", p4.client)
emptyChange = []
for d in data:
if 'shelved' in d:
# Archived\shelved, skip
continue
# Find files in this change:
files = p4.run("describe", d['change'])
if 'depotFile' not in files[0]:
emptyChange.append(d['change'])
if emptyChange:
for empty in emptyChange:
# Need to loop, can't delete multiple changes at once:
p4.run("change", "-d", empty)
print "Deleted empty changelists:", emptyChange
else:
print "No empty changelists to delete."
p4.disconnect()
return emptyChange
}}}
[[Perforce Python API docs|http://www.perforce.com/perforce/doc.current/manuals/p4script/03_python.html#1116373]]
From the [[float docs|https://docs.python.org/2/library/functions.html#float]]:
<<<
Note When passing in a string, values for {{{NaN}}} and Infinity may be returned, depending on the underlying C library. Float accepts the strings {{{nan}}}, {{{inf}}} and {{{-inf}}} for {{{NaN}}} and positive or negative infinity. The case and a leading + are ignored as well as a leading - is ignored for {{{NaN}}}. Float always represents {{{NaN}}} and infinity as {{{nan}}}, {{{inf}}} or {{{-inf}}}.
<<<
{{{
bad = [float(item) for item in ["nan", "inf", "-inf"]]
for b in bad:
print b, type(b)
}}}
{{{
nan <type 'float'>
inf <type 'float'>
-inf <type 'float'>
}}}
You can use this to test other floats against.
Some good stuff here:
https://stackoverflow.com/questions/3787908/python-determine-if-all-items-of-a-list-are-the-same-item
Presuming {{{items}}} is a sequence:
{{{
def all_same(items):
return all(x == items[0] for x in items)
}}}
Or:
{{{
if len(set(items)) == 1:
pass
}}}
Maybe there's more than this? A growing list of dev environments as I find them...
*[[Pythonista|http://omz-software.com/pythonista/]]
**[[Automating iOS: How Pythonista Changed My Workflow|http://www.macstories.net/stories/automating-ios-how-pythonista-changed-my-workflow]]
Also see [[Dictionary methods]]
Python Docs on [[Mapping Types|http://docs.python.org/lib/typesmapping.html]]
Also known as 'hash tables' or 'associative arrays'.
They are authored as a series of {{{key:value}}} pairs inside curly braces.
----
Good video on the guts of the dictionary:
http://python.mirocommunity.org/video/1591/pycon-2010-the-mighty-dictiona
----
''Tips and Tricks:''
{{{
# Simple creation:
d = {"duck": "eend", "water": "water"}
}}}
Get 'default' value (not sure why it's called 'set default'). If it can find the provided key, it returns that value. If it can't find the key, it will return {{{None}}}, unless you supply an optional value to return:
{{{
dic = {"A": 1, "B": 2, "C": 3}
print dic.setdefault("A")
1
print dic.setdefault("Q", "missing")
"missing"
}}}
Create by zipping two lists:
{{{
keys = ["key1", "key2"]
values = [23, 53]
D = dict(zip(keys, values))
# {'key2': 53, 'key1': 23}
}}}
Create with {{{enumerate}}}:
{{{
foo = ["a", "b", "c"]
d = dict(enumerate(foo))
print d
# {0: 'a', 1: 'b', 2: 'c'}
}}}
Concatenate two dicts:
{{{
d1 = {"a":1, "b":2, "c":3}
d2 = {"e":4, "f":5, "g":6}
d1.update(d2)
print d1
print d2
# {'a': 1, 'c': 3, 'b': 2, 'e': 4, 'g': 6, 'f': 5}
# {'e': 4, 'g': 6, 'f': 5}
}}}
Assignment:
{{{
foo = {}
foo["key"] = "value"
print foo
# {'key': 'value'}
}}}
Lookup:
{{{
d["duck"]
# "eend"
d["back"]
# raises KeyError exception
}}}
Delete, insert, overwrite:
{{{
del d["water"]
# {"duck": "eend", "back": "rug"}
d["back"] = "rug"
# {"duck": "eend", "back": "rug"}
d["duck"] = "duik"
# {"duck": "duik", "back": "rug"
}}}
Dictionaries can have lists as well:
{{{
dict["list"] = ["a", "b"]
# {'lista': ['a', 'b']}
dict["lista"] = dict["lista" + ["c"]
# {'lista': ['a', 'b', 'c']
}}}
Copy a dictionary:
{{{
D.copy()
}}}
Iterate through:
{{{
for key in D:
# stuff
}}}
Iterate over dictionary items in sorted fashion:
{{{
for key in sorted(D):
print key
}}}
Print all {{{key:value}}} pairs. (Need to convert the values to strings to catenate properly)
{{{
# old way, slower, not using iterators:
for key in d.keys():
print key + " : " + str(d[key])
# new way, faster, using dictionary iterator:
for key in D:
print key, str(D[key])
}}}
Remove an item from a dict (is there a better way?):
{{{
d = {"one":1, "two":2}
d = dict([key, d[key]] for key in d if key != "one")
print d
{'two': 2}
}}}
----
Dictionaries can hold other dictionaries:
{{{
# method1:
d = {"key":"value"}
d["subD"] = {"subKey":"subValue"}
print d
# {'subD': {'subKey': 'subValue'}, 'key': 'value'}
}}}
{{{
# method 2:
d = {"key":"value", "subD":{"subKey":"subValue"}}
print d
# {'subD': {'subKey': 'subValue'}, 'key': 'value'}
}}}
update sub-dictionary:
{{{
# method 1
subD = d["subD"]
subD["newSubKey"] = "newSubValue"
print d
# {'subD': {'newSubKey': 'newSubValue', 'subKey': 'subValue'}, 'key': 'value'}
}}}
{{{
# method 2
dicA = {}
dicA["dicB"] = {}
dicA["dicB"]["dicC"] = {}
dicA["dicB"]["dicC"]["dicD"] = {}
print dicA
# {'dicB': {'dicC': {'dicD': {}}}}
dicA["dicB"]["someList"] = ["a", "b", "c"]
dicA["dicB"]["dicC"]["dicCList"] = ["f", "g", "h"]
dicA["dicB"]["dicC"]["dicD"]["thingy"] = "dicD thing"
dicA["dicB"]["dicC"]["dicD"]["wingy"] = "dicD wing"
print dicA
# {'dicB': {'someList': ['a', 'b', 'c'], 'dicC': {'dicCList': ['f', 'g', 'h'], 'dicD': {'thingy': 'dicD thing', 'wingy': 'dicD wing'}}}}
}}}
----
Search and update sub dictionaries:
{{{
d = {}
# add our sub-dictionary
subDic = "info"
d[subDic] = {}
print d
# {'info': {}}
searchKey = "bob"
newValue = "human"
if d.has_key(subDic):
subD = d[subDic]
# does the sub-dictionary have a certain key?
if not subD.has_key(searchKey):
subD[searchKey] = newValue
print d
# {'info': {'bob': 'human'}}
}}}
A dictionary of lists:
{{{
d = {"one":[], "two":[1,3]}
# update list:
d["one"].append("spam")
print d["one"]
# ['spam']
# get val from list:
num = d["two"][1]
# 3
}}}
Python Docs on [[Mapping Types|http://docs.python.org/lib/typesmapping.html]]
{{{
>>> d = {"duck": "end", "water": "h20"}
>>> for thing in dir(d):
>>> print thing
clear
copy
fromkeys
get
has_key
items
iteritems
iterkeys
itervalues
keys
pop
popitem
setdefault
update
values
}}}
Also:
{{{
help ({})
}}}
[[eval|https://docs.python.org/3/library/functions.html#eval]] will evaluate a assignment expression based on some string, returning the results as the assignment:
{{{
one = 1
two = 2
}}}
{{{
evalThree = eval(f"{one} + {two}")
print(evalThree)
3
}}}
While [[exec|https://docs.python.org/3/library/functions.html#exec]] will evaluate the entire expression string: {{{exec}}} does not return, but instead executes the provided expression string in its entirety:
{{{
exec(f"execThree = {one} + {two}")
print(execThree)
3
}}}
While the above is a simple example of {{{exec}}}, sometimes you need to pass in the frame's globals and locals for modification:
{{{
exec(f"execThree = {one} + {two}", globals(), locals())
}}}
----
So:
{{{eval}}} handles the right side of an assignment expression:
{{{
someVar = eval("1+2")
}}}
While {{{exec}}} handles the entire expression, doesn't necessarily have to be an assignment expression, just used in this example
{{{
exec("someVar = 1+2")
}}}
Found here: http://nodebox.net/code/index.php/Math
{{{
from math import sqrt
# 2d points:
def distance(x0, y0, x1, y1):
return sqrt(pow(x1-x0, 2) + pow(y1-y0, 2))
}}}
----
Another solution I came up with, works with 2d or 3d points:
{{{
from math import sqrt
def distBetween(x, y):
return sqrt( sum( map( lambda z:pow(z[0]-z[1], 2), zip(x,y) ) ) )
}}}
http://easygui.sourceforge.net/
<<<
~EasyGUI is a module for very simple, very easy GUI programming in Python.
Experienced Pythonistas need support for quick and dirty GUI features. New Python programmers need GUI capabilities that don't require any knowledge of Tkinter, frames, widgets, callbacks or lambda. This is what ~EasyGUI provides. Using ~EasyGUI, all GUI interactions are invoked by simple function calls.
~EasyGUI is different from other ~GUIs in that ~EasyGUI is NOT event-driven. It allows you to program in a traditional linear fashion, and to put up dialogs for simple input and output when you need to. If you have not yet learned the event-driven paradigm for GUI programming, ~EasyGUI will allow you to be productive with very basic tasks immediately. Later, if you wish to make the transition to an event-driven GUI paradigm, you can do so with a more powerful GUI package such as anygui, ~PythonCard, Tkinter, wxPython, etc.
<<<
Apparently you can use them in Python, although they don't display in the Anaconda prompt...
* https://www.reddit.com/r/Python/comments/qy4iym/you_can_insert_emoji_using_nname_of_emoji/
* https://www.unicode.org/emoji/charts/full-emoji-list.html
* https://docs.python.org/3/library/unicodedata.html
* https://docs.python.org/3/howto/unicode.html
{{{
"\N{Sauropod}"
}}}
I've had good luck with openpyxl : https://pypi.org/project/openpyxl/
* https://openpyxl.readthedocs.io/en/stable/tutorial.html
* https://openpyxl.readthedocs.io/en/stable/usage.html
* https://openpyxl.readthedocs.io/en/stable/api/openpyxl.html
* [[Workbook|https://openpyxl.readthedocs.io/en/stable/api/openpyxl.workbook.workbook.html]] is the root object.
** [[Worksheet|https://openpyxl.readthedocs.io/en/stable/api/openpyxl.worksheet.worksheet.html|]] : Has one or more of these.
*** [[Cell|https://openpyxl.readthedocs.io/en/stable/api/openpyxl.cell.cell.html]] : Which are filled with these.
!Workbooks
Make a new Workbook
{{{
wb = Workbook()
wb = pyxl.load_workbook("path to xlsx")
}}}
Save:
{{{
wb.save("path to xlsx")
}}}
!Worksheets
Get the active Worksheet:
{{{
ws = wb.active
# Make some new ones:
ws1 = wb.create_sheet("Mysheet") # insert at the end (default)
ws2 = wb.create_sheet("Mysheet", 0) # insert at first positionws3 = wb.create_sheet("Mysheet", -1) # insert at the penultimate position
}}}
Set the Worksheet title:
{{{
ws.title = "New Title"
}}}
Get all the worksheet names:
{{{
sheets = wb.sheetnames
}}}
Set data:
{{{
ws['A1'] = 73
ws.append([5,6,7])
}}}
!Cels:
Getting cels:
{{{
c = ws['A4']
cell_range = ws['A1':'C2']
}}}
Assigning Data:
{{{
ws['A4'] = 4
c.value = 4
}}}
Both at the same time:
{{{
c = ws.cell(row=4, column=2, value=10)
}}}
!Rows/Columns
{{{
colC = ws['C']
col_range = ws['C:D']
row10 = ws[10]
row_range = ws[5:10]
}}}
{{{
for row in ws.iter_rows(min_row=1, max_col=3, max_row=2):
for cell in row:
print(cell)
}}}
{{{
for col in ws.iter_cols(min_row=1, max_col=3, max_row=2):
for cell in col:
print(cell)
}}}
{{{
rows = tuple(ws.rows)
columns = tuple(ws.columns)
}}}
I use [[Wing IDE]] for all my Python coding. Here is a hotkey you can use to open Windows Explorer to where the active document is saved. I map this to {{{Ctrl+E}}}, and it is saved in a module here:
{{{
C:\Users\<userName>\AppData\Roaming\Wing IDE 5\scripts\wingHotkeys.py
}}}
{{{
# wingHotkeys.py
import os
import wingapi
def exploreActiveDocument():
"""
For the open document, open a Windows Explorer to that directory.
"""
editor = wingapi.gApplication.GetActiveEditor()
if editor is None:
return
doc = editor.GetDocument()
filename = doc.GetFilename()
if os.path.isfile(filename):
path = os.path.split(filename)[0]
os.system('explorer %s'%path)
print "Explored to: %s"%path
else:
print "Current document doesn't have a valid path: %s"%filename
}}}
A link to all file object methods
http://docs.python.org/lib/bltin-file-objects.html
http://code.activestate.com/recipes/66527/
This is a nice little implementation in pure Python:
https://github.com/Vectorized/Python-KD-Tree
Via Biopython : This one may be faster, but relies on numpy / scipy
https://biopython.org/
https://biopython.org/DIST/docs/api/Bio.KDTree.KDTree%27.KDTree-class.html
Scikit learn: Built on ~NumPy, ~SciPy, and matplotlib
* https://scikit-learn.org/stable/index.html
* https://scikit-learn.org/stable/modules/neighbors.html
* https://scikit-learn.org/stable/modules/generated/sklearn.neighbors.KDTree.html
* https://stackoverflow.com/questions/48126771/nearest-neighbour-search-kdtree
What is a kd tree?
https://en.wikipedia.org/wiki/K-d_tree
----
If you have {{{numpy}}} and {{{scipy}}}.
[[Calculate closest points via KDTree with numpy and scipy]]
Given a [[package|Packages]] named {{{myPackage}}} setup like so:
*/pythonStuff (in Python path)
**/myPackage
***/{{{__init__.py}}}
***/{{{moduleA.py}}}
***/{{{moduleB.py}}}
How can you query the [[module]]s that live in {{{myPackage}}}?
!!!Solution A:
Use the tools Python provides you:
{{{
# testA.py
import pkgutil
import myPackage
modules = []
for p in pkgutil.iter_modules(myPackage.__path__):
modules.append(p[1])
print modules
}}}
prints:
{{{
['moduleA', 'moduleB']
}}}
After I wrote this, I found a blog post here doing something similar:
http://jeetworks.org/node/49
!!!Solution B:
Roll your own. I actually came up with this solution first (with help from the Python Tutor email list), before I found out about {{{pkgutil.iter_modules()}}}.
What we do is auto-populate the {{{__all__}}} attr in the package's {{{__init__.py}}} module. This is a special attribute that is designed to store what package modules are visible to the outside world. Normally these are authored by hand.
See docs on the package {{{__all__}}} attr [[here|http://docs.python.org/tutorial/modules.html#importing-from-a-package]]
{{{
# /myPackage/__init__.py
import os
import glob
# Fill our __all__ attr with the modules currently living in this package:
__all__ = []
packageDir = os.path.split(__file__)[0]
modules = glob.glob( os.path.join(packageDir, "*.py") )
for m in modules:
justModule = os.path.splitext(os.path.split(m)[-1])[0]
# Don't add itself to the list:
if justModule != '__init__':
__all__.append(justModule)
}}}
Then to test:
{{{
# testB.py
import myPackage
print myPackage.__all__
}}}
prints:
{{{
['moduleA', 'moduleB']
}}}
When you pickle Python classes, pickle stores the full package path to them. That way, when the data is reconstituted (unpickled), it can import those modules, instantiate those classes as part of the unpickling operation.
But what happens if you refactor your code after data has been pickled, so that the classes that were pickled now live in other modules/packages... or even have new names: All the pickled data is not entirely broken... can you fix it?
As it turns out, yes you can, based on a solution I found [[here|https://stackoverflow.com/questions/2121874/python-pickling-after-changing-a-modules-directory]] : You can create a new subclass around {{{pickle.Unpickler}}}, and override the {{{find_class}}} method. In there, you can 'redirect' the logic pickle uses to find the package paths, and even class names. This example doesn't change the class names, but you get the idea:
{{{
import pickle
class RenameUnpickler(pickle.Unpickler):
def find_class(self, module, name):
renamed_module = module
if module == "some.module.path" or module == "other.module.path":
if name == "ClassNameA":
renamed_module = "better.module.path"
elif name == "ClassNameB":
renamed_module = "even.better.module.path"
# This doesn't work, errors! :(
#return super(RenameUnpickler, self).find_class(renamed_module, name)
# But this works a-ok:
return pickle.Unpickler.find_class(self, renamed_module, name)
}}}
Then later, you call to it like this:
{{{
with open(path, 'rb') as inf:
# Nope
#storedData = pickle.load(inf)
# Yep
storedData = RenameUnpickler(inf).load()
}}}
General notes on floats and ints:
http://docs.python.org/lib/typesnumeric.html
https://docs.python.org/3/tutorial/floatingpoint.html
{{{
7/3
2 # obviously, we're missing something here...
7.0/3.0
2.3333333333333335 # more what we were after.
}}}
{{{
>>> floatFoo = 1.0
>>> for thing in dir(floatFoo):
>>> print thing
# there are no methods for floats?
}}}
I don't think so, they're //immutable//
An easy way to control the printed result of a small floating point number is with string formatting:
{{{
num = 12345.12567
print "%.2f" % num
# 12345.13
}}}
the {{{%.2f}}} will only display {{{2}}} places to the right of the decimal point, with rounding.
----
The {{{round()}}} function works pretty well too:
{{{
print round(1.23423423434, 3)
1.234
}}}
----
Also see:
*[[How can I reduce the precision of a floating point number?]]
*http://docs.python.org/library/stdtypes.html#string-formatting
*http://docs.python.org/library/functions.html#round
I found this code snippet a way down this page:
http://nodebox.net/code/index.php/Core_Image
(credit to Duane Bailey)
{{{
def fractal(x, y, depth=64):
z = complex(x, y)
o = complex(0, 0)
for i in range(depth):
if abs(o) <= 2: o = o*o + z
else:
return i
return 0 #default, black
pixels = []
w = h = 150
for i in range(w):
for j in range(h):
v = fractal(float(i)/w, float(j)/h)
pixels.append(color(v/10.0, v/20.0, v/10.0))
l = canvas.append(pixels, w, h)
}}}
[img[http://nodebox.net/code/data/media/coreimage-layers7c.jpg]]
I've not tried it myself yet, but it looked very elegant.
Also known as procedures (in other languages, if they //don't// [[return]] values), gives you a way to name a piece of code, and pass arguments to it. The '{{{def}}}' statement creates a 'function //object//'. Function objects can do work, [[return]] data, or do both. See [[Python docs|http://docs.python.org/ref/function.html]].
{{{
def square(x):
"""This is a 'docstring'. They're good to have,
so users know what the function is doing."""
return x*x
}}}
{{{
>>> print square(2)
4
}}}
<<<
''Note'': I wrote the below section before I really grasped the difference in concept between 'parameters' and 'arguments'. So //everything// I discuss below this note is refers to 'arguments only'. However, parameters and arguments are two different things, which I'll describe here first, and maybe get around to re-authoring the below text later ;)
A function can take a series of identifiers, also known as //parameters//:
{{{
def foo(parameter1, parameter2="defaultArgument"):
# do work
}}}
And when you call to the function you pass values, known as //arguments//, to the parameters:
{{{
foo('argument1')
}}}
Based on this example, the //parameter// {{{parameter2}}} has a //[[default argument|Default Arguments]]// with the string //value// of {{{"defaultArgument"}}}. If you don't pass an argument to {{{parameter2}}} when the function is called, then the //default argument// is used instead. The //parameter// {{{paramter1}}} has the argument {{{'argument1'}}} passed in.
So when 'parameters' are discussed, they refer to the 'identifier name' the function expects, and when 'arguments' are discussed, it refers to the 'values' passed into the function.
<<<
Functions can have [[argument]]s defined, and passed in, in four different ways. Check the tiddler on [[argument]]s for details.
Crazy as it sounds (to me, when I first learned it), functions can be nested in functions. However, I hear as a general rule this should be avoided, just to make the code simpler to understand. I have yet to find a reason to do this... ;)
{{{
def func(A):
def nestFunc(B):
return A ** B
return nestFunc
foo = func(2)
print foo
# <function nestFunc at 0x00C01A70>
print foo(4)
# 16
}}}
In the above example, we define a function {{{func()}}}, that has a nested function {{{nestFunc()}}}. When you execute {{{func()}}}, it passes its [[argument]] to {{{nestFunc}}}, and then //returns// the function object {{{nestFunc()}}}, named {{{foo}}}. When you then execute that function object passing in some argument, the new function object returns back the square of that value. What's interesting, is even after {{{func()}}} exits, the newly created function object {{{foo}}} still remembers the local variable that was passed into it ({{{A}}}). I read that earlier version of Python (<2.5) would fail, because they'd not search the enclosing scope of the defined function. But now a'days that appears to be handled nicely...
----
Functions //are// objects, and can be passed around just like any other object type (string, float, etc). They're just variables assigned in the current scope. They can be stored in other data structures, and called to later:
{{{
def printMe(x):
print x
name1, name2 = printMe, printMe
names =[(name1, "george"), (name2, "larry")]
for(func, arg) in names:
func(arg)
# george
# lary
}}}
----
[[lambda|Understanding lambda]]'s are also called 'anonymous functions'. They are 'expression forms' that generate function objects.
----
You can also make '''generator functions''' (see Python docs [[here|http://docs.python.org/tut/node11.html#SECTION00111000000000000000000]], and [[here|http://docs.python.org/ref/yieldexpr.html]]). Generators allow values to be sent back on at at time, so they can be resumed at a later point. They 'generate' a sequence of values over time. This is done by introducing the {{{yield}}} statement ([[python docs|http://docs.python.org/ref/yield.html]]) to the function instead of a [[return]] statement. You still can have a {{{return}}} statement in the function: If it is reached, the function is exited.
{{{
def genMult(num, mult):
for i in range(num):
yield mult * i
x = genMult(10, 5)
print x.next()
# 0
print x.next()
# 5
print x.next()
# 10
# etc...
}}}
Generator objects have a {{{.next()}}} method that can be called to to provide the next iteration of data.
It is explained that an advantage of generators is that they only process data 'one step at a time', rather than 'all at once' based on a normal function def. This means they can be more efficient when dealing with large lists.
When done they raise a {{{StopIteration}}} exception. They also have methods {{{.send(value)}}} and {{{.throw(type)}}}.
----
You can also do a mashup of list comprehensions and generators to make '''generator expressions'''. They act like list comprehensions, but are surrounded in parenthesis instead of square brackets. See notes on [[list comprehension]].
----
Function objects (yes, functions are objects) have a number of special attributes that can be accessed (docs found [[here|http://docs.python.org/reference/datamodel.html#the-standard-type-hierarchy]]):
| ''Attribute'' | ''Meaning'' | |
| {{{func_doc}}} |The function’s documentation string, or None if unavailable | Writable |
| {{{__doc__}}} | Another way of spelling func_doc | Writable |
| {{{func_name}}} |The function’s name | Writable |
| {{{__name__}}} |Another way of spelling func_name | Writable |
| {{{__module__}}} |The name of the module the function was defined in, or None if unavailable. | Writable |
| {{{func_defaults}}} |A tuple containing default argument values for those arguments that have defaults, or None if no arguments have a default value | Writable |
| {{{func_code}}} |The code object representing the compiled function body. | Writable |
| {{{func_globals}}} |A reference to the dictionary that holds the function’s global variables — the global namespace of the module in which the function was defined. | Read-only |
| {{{func_dict}}} |The namespace supporting arbitrary function attributes. | Writable |
| {{{func_closure}}} |None or a tuple of cells that contain bindings for the function’s free variables. | Read-only |
Official Python list:
http://wiki.python.org/moin/PythonGames
I could duplicate it all here, but what's the point?
----
*[[Kivy|http://kivy.org/#home]]
!pydoc:
http://www.python.org/doc/lib/module-pydoc.html
{{{pydoc}}} is a built-in Python module.
Here's a simple example from the commandline:
{{{
>python -m pydoc -w C:\pystuff\myModule.py
}}}
This will save this file:
{{{
C:\Python26\Lib\myModule.html
}}}
To make docs for all modules in a dir, you can do the below options. Also, by browsing to that dir directly, and calling to the full path of where {{{pydoc.py}}} is located, it will save the resultant .html files in that dir:
{{{
C:\pystuff>python C:\Python26\Lib\pydoc.py -w C:\pystuff
}}}
It should be noted that {{{pydoc}}} needs to import the module to build documentation on it. If the imported module imports other modules that for some reason aren't part of the current Python path, it will raise a {{{exceptions.ImportError}}}.
!Epydoc:
http://epydoc.sourceforge.net/
I'm currently using this to generate documentation. I like it over {{{pydoc}}} because it won't get hung up on missing imported modules: Working in Autodesk's Maya, It wrappers its scripting language mel in Python. but the bulk of it's {{{maya.cmds}}} package is actually generated on the fly when the program starts, there are no actual modules on disk. This cause imports of them to fail for things like {{{pydoc}}} (since Maya isn't running when the documentation is being generated), but {{{Epydoc}}} can work around it.
!docutils
http://docutils.sourceforge.net/
!Sphinx
http://sphinx.pocoo.org/
Conceptually, it's better to have the user access a method for data, rather than an attribute directly. You can write methods to interface this data for the user:
{{{
class Foo(object):
def __init__(self):
self.__val = 0
def get_val(self):
return self.__val
def set_val(self, new_val):
self.__val = new_val
}}}
I seem to have a growing number of subjects on this topic :) Let's collect some more info here!
In a module, you can have data defined in a variety of different ways: The module itself, functions, classes, etc. How can that module query both where it lives on disk, and it's module path, relative to any possible [[package|Packages]] it lives in?
*{{{__file__}}} is a special module attribute that stores the path to where is is saved. This can be absolute or relative depending on the circumstance.
*{{{__module__}}} is a special class attribute storing the module where the class was created.
*{{{__name__}}} is a special module attribute (for classes too, but for class names) that returns back the name of the module it's called in. The only exception to this is that if the module in question is being executed directly (from a command shell, icon-double-click, etc) this value will = '{{{__main__}}}'
Docs on [[special attributes|http://docs.python.org/library/stdtypes.html#special-attributes]]
{{{
# nametest.py in the animation package
print "Module full path:", __file__
class Spam(object):
def __init__(self):
print "Class defined in module:", self.__module__
def main():
print "Function defined in module:", __name__
}}}
Execution:
{{{
import animation.nametest
animation.nametest.main()
eggs = animation.nametest.Spam()
}}}
Results:
{{{
Module full path: D:\pystuff\animation\nametest.py
Function defined in module: animation.nametest
Class defined in module: animation.nametest
}}}
----
Also see:
*[[How can I query where a module is saved?]]
*[[How can a class query where it was created?]]
*[[How can a module reference where itself has been saved?]]
*[[What's up with: if __name__ == "__main__":]]
*[[How can a module query relative directories to where it has been saved?]]
Given a list of names, that may or may not have numbers on the end of them, add a certain value to each of the numbers, and give back a new list of names. Be conscious of padding:
{{{
import re
increment = 1
files = ["file0001", "file0022", "file0033", "filex"]
newFiles = []
for f in files:
try:
num = re.findall('[0-9]+$', f)[0]
name = f[:-(len(num))] + str(int(num)+increment).zfill(len(num))
newFiles.append(name)
except IndexError:
newFiles.append(f)
print newFiles
}}}
{{{
['file0002', 'file0023', 'file0034', 'filex']
}}}
{{{
mylist = [6, 5, 4, 3, 2, 1, 0]
print mylist.index(4)
# 2
}}}
The number 4 is in the 2nd index position in the list. If it isn't in the list, it will raise a {{{ValueError}}} exception.
For example, pretend you have a custom class that has both attrs and methods that hold, or return data:
{{{
# Secret code the user knows nothing about:
class Spam(object):
def __init__(self):
self.value = 23
def myMethod(self):
return self.value*2
}}}
You're on an exploratory mission, so you're using the {{{dir()}}} command for some object inspection. But {{{dir}}} returns the //string names// of the attrs on the object, not an actual pointer to those objects themselves:
{{{
eggs = Spam()
attrStrs = dir(eggs)
print attrs
# After a bunch of built-in stuff, you see some interesting values at the end:
# [..., 'myMethod', 'value']
}}}
You now want to get the values held in those attrs, but you don't know if they're methods (callable) or not. Plus, how can you call to a string version of an attr name? That's where the {{{getattr()}}} command comes into play:
{{{
attrs = []
for attrStr in ['myMethod', 'value']:
# Convert to object representation:
objAttr = getattr(eggs, attrStr)
if callable(objAttr):
print "eggs.%s() :"%attrStr, objAttr()
else:
print "eggs.%s :"%attrStr, objAttr
}}}
And it prints out:
{{{
eggs.myMethod() : 46
eggs.value : 23
}}}
The {{{getattr()}}} command returns the physical attribute\method object. By passing that to the {{{callable()}}} command, we know whether or not it's a method or not, so we know if we need to 'call' to the method to get the values, or just 'print' the attribute's results.
I recently ran into this problem: I had multiple lists of multiple items. I needed to find items in the supplied lists that only occurred once in all the lists. I thought I could implement this via {{{sets}}}, but I just couldn't make it happen. Maybe it is doable? At any rate, here is the quick solution I came up with:
For each item in each list, put it in a dict, and count the number of times its been added. Return only those things added once.
{{{
def getUniqueItems(*lists):
"""
*lists : each item passed in is expected to be a list.
return : list : Of unique items only found once in all lists.
"""
data = {}
for nodes in lists:
for item in nodes:
if item in data:
data[item] += 1
else:
data[item] = 1
result = [item for item in data if data[item] == 1]
return result
}}}
{{{
a = ['a','b','c','d']
b = ['b','c','d','e']
c = ['c', 'd', 'e', 'f']
unique = getUniqueItems(a,b,c)
# ['a', 'f']
}}}
Found here: http://nodebox.net/code/index.php/Math
{{{
# Fibonacci sequence
def fib(n):
if n == 0: return 0
if n == 1: return 1
if n >= 2: return fib(n-1) + fib(n-2)
def goldenratio(n, f=4):
# Returns two proportional numbers whose sum is n.
f = max(1, min(f, 10))
n /= float(fib(f+2))
return n*fib(f+1), n*fib(f)
}}}
Thought I would log pages that show 'good code examples' in Python.
----
!Conventions
*[[PEP8|http://python.org/dev/peps/pep-0008/]], of course.
*[[Code Like a Pythonista: Idiomatic Python|http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html]]
!Videos:
*[[PyCon 2011: Python for High Performance Computing|http://blip.tv/file/4881240]]
!Examples \ Recipes:
*Good examples that start at one line and work up to 33 lines:
**http://wiki.python.org/moin/SimplePrograms
*Recipes:
**http://code.activestate.com/recipes/langs/python/
*Working with the {{{itertools}}} module:
**http://docs.python.org/dev/library/itertools.html#recipes
*Sorting mini-how to:
**http://wiki.python.org/moin/HowTo/Sorting
!Visualization:
Tools to help visualize efficiency
*[[RunSnakeRun|http://www.vrplumber.com/programming/runsnakerun/]] : ...is a small GUI utility that allows you to view (Python) cProfile or Profile profiler dumps in a sortable GUI view. It allows you to explore the profiler information using a "square map" visualization or sortable tables of data.
*[[Gprof2Dot|http://code.google.com/p/jrfonseca/wiki/Gprof2Dot]] : ...is a Python script to convert the output from many profilers into a dot graph.
*[[pycallgraph|http://pycallgraph.slowchop.com/]] : ...is a Python module that creates call graphs for Python programs.
!Efficiency:
*[[Python Idioms and Efficiency|http://bayes.colorado.edu/PythonIdioms.html]]
*[[Python Speed/Performance Tips|http://wiki.python.org/moin/PythonSpeed/PerformanceTips]]
*[[Python Patterns - An Optimization Anecdote|http://www.python.org/doc/essays/list2str.html]] - Guido van Rossum
*[[Efficient String Concatenation in Python|http://www.skymind.com/~ocrow/python_string/]]
*[[Python 3: Informal String Formatting Performance Comparison|http://www.protocolostomy.com/2011/01/02/python-3-informal-string-formatting-performance-comparison/]]
----
{{{array}}} module: "Efficient arrays of numeric values"
*http://docs.python.org/library/array.html
----
!!!Notes from the above docs:
From: http://docs.python.org/dev/library/itertools.html#module-itertools
>...the multiplication operator can be mapped across two vectors to form an efficient dot-product:
{{{
import operator
from itertools import imap
def dotproduct(vec1, vec2):
return sum(imap(operator.mul, vec1, vec2))
print dotproduct((2,2,2), (3,3,3))
# 18
}}}
>Note, many of the above recipes ''can be optimized by replacing global lookups with local variables defined as default values''. For example, the dotproduct recipe can be written as:
{{{
def dotproduct(vec1, vec2, sum=sum, imap=imap, mul=operator.mul):
return sum(imap(mul, vec1, vec2))
}}}
----
Stuff I've read:
*"Python accesses local variables much more efficiently than global variables."
*"...function call overhead in Python is bigger than for loop overhead." (guido)
*"...local variable lookups are much faster than global or built-in variable lookups: the Python "compiler" optimizes most function bodies so that for local variables, no dictionary lookup is necessary, but a simple array indexing operation is sufficient.""" (guido)
----
Looping:
*Use {{{map}}} rather than a for-loop, since {{{map}}} takes place entirely in the C API and never has to bind loop variables to Python objects.
**Calls to {{{map}}} happen in C, while calls external to it happen in the bytecode interpreter, which is slower.
*List comprehensions are often as fast or faster than equivalent use of {{{map}}}.
**Very important: don't put a loop into the final test case of a list comprehension: It appears to re-run that loop each test. Notes below.
{{{
# Standard:
newlist = []
for word in oldlist:
newlist.append(word.upper())
# Faster:
newlist = map(str.upper, oldlist)
# Fastest:
newlist = [s.upper() for s in oldlist]
# Note, you do *not* want to do this:
newlist = [s.upper() for s in makeOldList()]
# Since it looks like it may run the makeOldList() func every loop (bad).
}}}
----
Making strings:
{{{
# No:
for s in strings:
result += s
# Yes:
result = ''.join(strings)
}}}
Although it looks like current version of Python (2.6ish) don't suffer this problem, and string concatenation is just as fast as the join method:
http://wiki.python.org/moin/ConcatenationTestCode
----
Use coercion if an object must be a particular type:
{{{
# No:
isinstance(str, x)
# Yes:
str(x)
}}}
----
To quickly reverse-sort a list:
{{{
list.sort()
list.reverse()
}}}
----
Finding largest (or smallest) value in a list.
{{{
from random import randint
bigListA = [randint(0, 1000) for item in range(1000)]
bigListB = bigListA[:]
bigListC = bigListA[:]
def sortA():
biggestA = sorted(bigListA)[-1]
def sortB():
biggestB = max(bigListB)
def sortC():
bigListC.sort()
biggestC = bigListC[-1]
}}}
Running the above code through a timer gave these results:
{{{
Completed 1000 iterations of sortA() in 0.281000 seconds, 0.000281 per loop
Completed 1000 iterations of sortB() in 0.028000 seconds, 0.000028 per loop
Completed 1000 iterations of sortC() in 0.023000 seconds, 0.000023 per loop
}}}
{{{max()}}} has nearly a 10x speed increase over {{{sorted()}}}, and the in-place {{{list.sort()}}} is roughly 21% faster than {{{max()}}}.
----
To swap variables without making temporary ones:
{{{
a, b = b, a
}}}
----
Use tests for object identity when appropriate:
{{{
# No:
if x != None
# Yes:
if x is not None:
}}}
It is much more efficient to test objects for identity than equality, because identity only checks their address in memory (two objects are identical if they are the same object in the same physical location) and not their actual data
----
Use dictionaries (or sets) for searching, not lists. Searching a list for an item is linear-time, while searching a dict or set for an item is constant time. This can often let you reduce search time from quadratic to linear.
----
Reversing lists: Which is faster: Adding a bunch of items to a list and reversing it, or inserting each item to the beginning of the list? (from the book "Python Algorithms")
Append\reverse:
{{{
count = 10**5
nums = []
for i in range(count):
nums.append(i)
nums.reverse()
}}}
Insert in front:
{{{
count = 10**5
nums = []
for i in range(count):
nums.insert(0, i)
}}}
Running each of these through a timer tool, "append\reverse" took 0.297 seconds, while "insert in front" took 5.516 seconds (18.5x slower, on my old laptop).
So it's safe to say that {{{list.append()}}} is //way more efficient// than {{{list.insert()}}} :-)
----
https://colab.research.google.com/
It's like a [[JUPYTER]] Notebook, but in the cloud, with just about every Python package you could ever want, running in the cloud, on a Google computer.
https://research.google.com/colaboratory/faq.html
----
! External data: Local Files, Drive, Sheets, and Cloud Storage
They have their own colab here covering all this:
https://colab.research.google.com/notebooks/io.ipynb
But my other notes are below before I found that page
----
! How do I access Google Drive?
!! Mount it via the Files Menu
From the 'Files' menu (on the left), press the 'Google Drive Folder' icon. This will request your permission to connect to google drive, and it will show up at the root level as:
{{{
/drive
}}}
!!Mount it via code
{{{
from google.colab import drive
drive.mount('/drive')
# This will trigger a google security feature requiring you to choose the google account to use, and then pass in a special password.
}}}
If you had previously mounted via the 'Files Menu', that mount will be gone: Instead, go back to the files menu, hit the 'up' button to get to root, then navigate to:
{{{
/drive
}}}
----
! Embedding Images From Google Drive
!! Via Markup
* Open your google drive and find the image you want
* RMB on the file & 'get link' : Be sure to change it to a 'sharable link'. Copy that, for example:
{{{
https://drive.google.com/file/d/1trNFk5ig2YMWxlGSygubGMEdmmlRJy8N/view?usp=sharing\
}}}
* To embed that image, copy just the image ID, which is {{{1trNFk5ig2YMWxlGSygubGMEdmmlRJy8N}}}
* You can then use this code snippet:
{{{
![](https://drive.google.com/uc? )
}}}
* Adding the ID in after the '{{{?}}}':
{{{
![](https://drive.google.com/uc?id=1trNFk5ig2YMWxlGSygubGMEdmmlRJy8N)
}}}
!! Via Code
* Get the path to your image via the file-browser on the left:
* RMB -> Copy path
* Paste it into the code below:
{{{
from IPython.display import Image
Image('/content/drive/MyDrive/Colab Notebooks/ML/data/car-photo.png')
}}}
----
! Saving Data To Google Drive
Mount the drive as shown above.
Make your paths relative to the /drive mount, and exist:
{{{
import pickle
pth = '/drive/MyDrive/some folder/mydata.pkl'
myData = ["Data", "Goes", "Here"]
#pickle.dump(myData, open(pth, "wb"))
}}}
----
! Show Installed Package Versions & Upgrade Them
More detailed notes here:
https://colab.research.google.com/notebooks/snippets/importing_libraries.ipynb#scrollTo=6km1lWMF2kAm
{{{
!pip show pandas
}}}
----
!Timing and profiling
https://colab.research.google.com/github/jakevdp/PythonDataScienceHandbook/blob/master/notebooks/01.03-Magic-Commands.ipynb
https://colab.research.google.com/github/jakevdp/PythonDataScienceHandbook/blob/master/notebooks/01.07-Timing-and-Profiling.ipynb
Magic commands come in two flavors: line magics, which are denoted by a single {{{%}}} prefix and operate on a single line of input, and cell magics, which are denoted by a double {{{%%}}} prefix and operate on multiple lines of input.
* {{{%time}}}: Time the execution of a single statement
* {{{%timeit}}}: Time repeated execution of a single statement for more accuracy
* {{{%prun}}}: Run code with the profiler
* {{{%lprun}}}: Run code with the line-by-line profiler
* {{{%memit}}}: Measure the memory use of a single statement
* {{{%mprun}}}: Run code with the line-by-line memory profiler
! Converting code cels to markdown
* On windows, hold down ctrl+m, tap 'm'.
* On mac, hold down cmd+m, tap 'm'.
! Converting markdown to code:
* On windows, hold down ctrl+m, tap 'y'.
* On mac, hold down cmd+m, tap 'y'.
! See all the shortcuts:
* On windows, hold down ctrl+'m', press 'h'
* On mac, hold down cmd+'m', press 'h'.
! Show the docstring:
* On windows : ctrl+shift, press 'space'
* On mac: cmd+shift, press 'space'
----
! Loading Extensions
{{{
# Load TensorBoard notebook extension
%load_ext tensorboard
}}}
Found this snippet online by Stephen Akiki:
http://code.activestate.com/recipes/577282-finding-the-gcd-of-a-list-of-numbers-aka-reducing-/
{{{
def GCD(a,b):
a = abs(a)
b = abs(b)
while a:
a, b = b%a, a
return b
def GCD_List(list):
return reduce(GCD, list)
}}}
{{{
print GCD_List([8, 24, 12])
# 4
}}}
(Referenced from Learning Python by Mark Lutz)
Of the built-in //object types//, how are they generally organized?
http://www.python.org/doc/current/lib/module-types.html#l2h-858
http://docs.python.org/reference/datamodel.html#the-standard-type-hierarchy
http://docs.python.org/library/stdtypes.html
*Numbers (immutable)
**Integers
***Integer
***Long
***Boolean
**Float
**Complex
**Set
**Decimal
*Collections
**Sequences
***Immutable
****String
****Unicode
****Tuple
***Mutable
****List
**Mappings
***Dictionary
*Callables
**Functions
**Class
**Method
***Bound
***Unbound
*Other
**Module
**Instance
**File
**None
*Internals
**Type
**Code
**Frame
**Traceback
----
Also see:
*[[What are Pythons built in types?]]
Python ships with many 'built-in' functions and modules. I'm used to the scripting language MEL, which has a core library of 'mel commands' (equivalent to functions) and associated 'mel scripts' (equivalent to modules). But coming to Python, the way it delivers and organizes its data seemed a bit more confusing. But I think I've figured how how it breaks down:
*Python ships with many (built-in) [[functions|Function]], which live in the {{{__builtin__}}} //module//. These functions include such as {{{abs}}}, {{{dir}}}, {{{help}}}, {{{map}}}, {{{open}}}, {{{raw_input}}}, {{{range}}}, etc, which flush out the basic requirements of the language.
**Link to the full list of built-in functions [[HERE|http://docs.python.org/lib/built-in-funcs.html]]
{{{
# if you want to pull help on __builtin__, you need to import it first:
import __builtin__
help(__builtin__)
}}}
*Python ships with many (built in) [[module]]s (of which {{{__builtin__}}} from above is a member). These obviously extend the built-in functions, and include such as {{{sys}}}, {{{os}}}, {{{re}}}, {{{pickle}}}, etc. Each of these usually has many associated functions that you end up accessing, and not the module name itself.
**Link to the 'Global Module Index' [[HERE|http://docs.python.org/modindex.html]]
**Install location: {{{..\PythonXX\Lib\}}}
http://docs.python.org/library/time.html#time.sleep
{{{
import time
print "waiting half a second:"
time.sleep(.5)
print "done!"
}}}
Presuming there are two items per index:
{{{
x = [1,2,3,4]
y = ["a", "b", "c", "d"]
zipped_xy = zip(x,y)
print zipped_xy
# [(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd')]
unzipped_x, unzipped_y = zip(*zipped_xy)
print unzipped_x
print unzipped_y
# (1, 2, 3, 4)
# ('a', 'b', 'c', 'd')
}}}
Thanks to tip from Mason Sheffield.
Via the 'Python Image Library' (PIL)
http://www.pythonware.com/products/pil/index.htm
"The Python Imaging Library (PIL) adds image processing capabilities to your Python interpreter. This library supports many file formats, and provides powerful image processing and graphics capabilities."
I ran into a situation where I wanted to pass in an arbitrary number of keyword [[arguments|argument]] to a new object, and have them all added as [[attributes|attribute]]. This is what I came up with, using {{{setattr}}}:
{{{
class Spam(object):
def __init__(self, **kwargs):
for arg in kwargs:
setattr(self, arg, kwargs[arg])
spam = Spam(argA=23)
for attr in dir(spam):
if not attr.startswith('__'):
print attr, " : ", eval('spam.%s'%attr)
}}}
{{{
argA : 23
}}}
Certain packages expect to be placed in Python's {{{\site-packages}}} dir, which by default lives here:
{{{
C:\Python26\Lib\site-packages
}}}
But maybe you want to set up a {{{site-packages}}} dir somewhere else. How to do?
Easy enough, via the {{{site}}} module:
{{{
newPackageDir = "c:/temp/hackPackages"
site.addsitedir(newPackageDir )
}}}
http://docs.python.org/library/site.html#site.addsitedir
----
Also see:
*[[Using the sitecustomize & usercustomize modules]]
*[[How can I set Python's path?]]
I don't know if this is the best way to do it, but //sometimes// you need a module to import some other module that has already imported it. Maybe, it needs to grab a function from that module to use in itself, and vice versa.
You can't have each module import each other directly, Python will get a cyclic loop error. Below is one solution for this problem.
Here, we author moduleA, that imports moduleB, and executes its spam() function.
{{{
# moduleA.py
import moduleB
def funcA1():
pass
def funcA2():
moduleB.funcB1()
}}}
Here, we author moduleB, that also needs to access part of moduleA: To do this, we do a 'from' import //inside// of the function that needs access to the imported function:
{{{
# moduleB.py
def funcB1():
pass
def funcB2():
from moduleA import funcA1
funcA1()
}}}
Sometimes I want to catch an exception, print some useful info to the user, and then also print the traceback info from the exception as well. One way to do it is listed below.
Docs:
*http://docs.python.org/library/traceback.html
*http://docs.python.org/library/sys.html#sys.exc_info
*http://docs.python.org/library/exceptions.html
----
Updated info: This will get the traceback info as a list. So many hoops to jump through though!
{{{
import sys
import traceback
try:
myCode()
except Exception, e:
tb = sys.exc_info()[2]
tbExtract = traceback.extract_tb(tb)
tbList = traceback.format_list(tbExtract)
print "Traceback:"
for line in tbList:
print line
print "Exception", e
}}}
----
To do this, we have to import the {{{traceback}}} and {{{sys}}} modules: The third item {{{sys.exc_info()}}} returns is a {{{traceback}}} object, and we can use the {{{traceback}}} module's {{{print_tb()}}} function to print out interesting info about it.
Make a module that will raise an exception:
{{{
# exceptionMaker.py
def main():
raise Exception("This is an exception in exceptionMaker.py")
}}}
This module will catch the exception, and print out useful info in the process.
{{{
# tracebackCatcher.py
import sys
import traceback
import exceptionMaker
try:
exceptionMaker.main()
except Exception, e:
tb = sys.exc_info()[2]
print "Traceback:"
traceback.print_tb(tb)
print "traceback type:", type(tb)
print "Exception type:", type(e)
print "Exception.args:", e.args
# Deprecated in Python 2.6 and newer, just use
# e.args[0] instead:
#print "Exception.message:", e.message
}}}
Run {{{tracebackCatcher.py}}}:
{{{
import tracebackCatcher
}}}
prints:
{{{
Traceback:
File "D:\python\tracebackCatcher.py", line 8, in <module>
exceptionMaker.main()
File "D:\python\exceptionMaker.py", line 4, in main
raise Exception("This is an exception in exceptionMaker.py")
traceback type: <type 'traceback'>
Exception type: <type 'exceptions.Exception'>
Exception.args: ('This is an exception in exceptionMaker.py',)
}}}
You can also write the traceback data to a log file:
{{{
with open(failFile, mode='a') as f:
traceback.print_tb(tb, file=f)
}}}
----
The more I used this method, the more I wanted to capture the traceback info for use elsewhere in my code. But uless I'm missing something, the traceback model gives you no way to easily access the traceback info: You can print it, and as mentioned above you can write it to a file. But how can you just get it in a list?
The below technique prints the traceback into to a temp file, then the guts of the temp file are extracted as a list. Seems like overkill, but it works.
{{{
# awesomeFile.py
import sys
import traceback
import tempfile
def superFail():
print "start!"
raise Exception("Oh noz, and exception!")
print "end!"
def main():
tbLines = []
try:
superFail()
except Exception, e:
tb = sys.exc_info()[2]
temp = tempfile.TemporaryFile()
traceback.print_tb(tb, file=temp)
temp.seek(0)
tbLines = [item.strip() for item in temp]
temp.close()
print "Traceback capture:"
for line in tbLines:
print "\t",line
print "\tEncountered Exception:", e
}}}
Running main() in that module prints:
{{{
start!
Traceback capture:
File "<awesomeFile.py>", line 16, in main
File "<awesomeFile.py>", line 9, in superFail
Encountered Exception: Oh noz, and exception!
}}}
[[os.path.getsize(pathToMyFile)|http://docs.python.org/2/library/os.path.html#os.path.getsize]]
Humans make mistakes. So it's important to check that your xml file is well-formed.
Here's two xml files to test. The second one has a bad tag:
{{{note.xml}}}:
{{{
<?xml version="1.0" encoding="ISO-8859-1"?>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
}}}
{{{note_bad.xml}}}: (see the last tag, it has an extra 's')
{{{
<?xml version="1.0" encoding="ISO-8859-1"?>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</notes>
}}}
First, a parser object is created. Then a (generic) content handler is added to the parser. Then with a {{{try}}} statement runs, catching exceptions resulting from poorly formed xml documents:
{{{
from xml.sax.handler import ContentHandler
import xml.sax
xmlFiles = ["note.xml", "note_bad.xml"]
# create the parser
xmlparser = xml.sax.make_parser()
# attach a generic content handler to parser:
xmlparser.setContentHandler(ContentHandler())
# Parse the files and handle exceptions:
for xmlF in xmlFiles:
try:
xmlparser.parse(xmlF)
print "%s is well formed!" % xmlF
except Exception, err:
print "Problem: %s:\n\t %s is not a well-formed file :(" % (err, xmlF)
}}}
{{{
c:\temp\xml\note.xml is well formed!
Problem: c:\temp\xml\note_bad.xml:8:2: mismatched tag:
c:\temp\xml\note_bad.xml is not a well-formed file :(
}}}
For windows, you can call to the {{{where}}} command via a shell. For linux/unix, you can use the {{{which}}} command in a shell.
In Python3, you can use:
{{{
import shutil
appPath = shutil.which("myApp.exe")
print(appPath)
C:\path\to\myApp.exe
}}}
To keep the variable around, but give it 'no value' irregardless of what type of object the pointed too, you can set it to {{{None}}}. This however physically changes the type of object it points to as {{{NoneType}}}: It's still pointing to an object is simply a "None" object:
{{{
spam = "a string"
print spam
>>> a string
print type(spam)
>>> <type 'str'>
spam = None
print spam
>>> None
print type(spam)
>>> <type 'NoneType'>
}}}
If you want to completely delete the variable (unbind the name \ object reference), you can use the {{{del()}}} function:
{{{
del(spam)
print spam
>>> Traceback (most recent call last):
>>> File "<string>", line 1, in <string>
>>> NameError: name 'spam' is not defined
}}}
If you want to 'clear' the object the variable points at, but keep its object type the //same as when it was last defined//, you can use this method:
{{{
# make a dictionary:
spam = {"key1":"value1", "key2":"value2"}
print spam
>>> {'key2': 'value2', 'key1': 'value1'}
spam = spam.__class__()
print spam
>>> {}
print type(spam)
>>> <type 'dict'>
}}}
I've heard you can use sets, but this looses ordering and removes dupes. If you care about ordering and need the dupes, you can use this:
{{{
import itertools
lists = [[1,2,3], [4,5,6], [7,8,9]]
combined = [item for item in itertools.chain(*lists)]
print combined
# [1, 2, 3, 4, 5, 6, 7, 8, 9]
}}}
https://docs.python.org/2/library/itertools.html#itertools.chain
{{{
def mergeDict(dict1, dict2):
"""
Return a new dictionary that is the merged version of the two provided.
"""
dict3 = dict1.copy()
dict3.update(dict2)
return dict3
}}}
Mac's come pre-installed with Python (awesome). However, 64-bit Python isn't as widespread as 32-bit, so sometimes you need to help you Mac to tell it what version to use.
In a Mac shell:
{{{
defaults write com.apple.versioner.python Prefer-32-Bit -bool yes
}}}
And here's some Mac docs:
http://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man1/python.1.html
I had a need to convert a string into an integer, for storing on an integer type attribute. Later, I needed to read that int back into a string. Solution I came up with:
{{{
import string
ASCII_CHARS = list(string.ascii_letters + string.digits + string.punctuation)
# 96 characters in ASCII_CHARS, so we only need to pad two levels:
INDEX_STRS = ["%02d"%i for i in range(len(ASCII_CHARS))]
def strToInt(word):
"""
Convert the provided string into an integer value that can be brought back
later by intToStr.
Used by shroud.SAttr.create when making enum attrs: This will generate a
unique int value for the provided string.
"""
# Add an extra '1' on the front of the number, so the first int won't loose
# it's (possbily) 0 first char:
intStr = "1"
for char in word:
i = ASCII_CHARS.index(char)
intStr += INDEX_STRS[i]
return intStr
def intToStr(number):
"""
Turn an int into a string, based on a previous conversion by strToInt.
"""
# Pop off the "1" at the front auto-added by strToInt:
intStr = str(number)[1:]
split = [intStr[i:i+2] for i in range(0, len(intStr), 2)]
word = ""
for strNum in split:
i = INDEX_STRS.index(strNum)
letter = ASCII_CHARS[i]
word += letter
return word
}}}
{{{
word = "word"
theInt = sUtils.strToInt(word)
print theInt
# 122141703
theWord = sUtils.intToStr(theInt)
print theWord
# 'word'
}}}
{{{
from ast import literal_eval
s = "1.5"
val = None
try:
val = literal_eval(s)
except ValueError: # if s was a string, not a number
val = s
print val, type(val)
1.5 <type 'float'>
}}}
These convert you code into what is known as 'frozen binaries'.
* [[PyOxidizer|https://pyoxidizer.readthedocs.io/en/latest/getting_started.html]]
*[[Nuitka|http://nuitka.net/pages/overview.html]]
** I've tried this a bit, seems super easy to break. Anything with very basic code and minimal imports will work. But calling to a higher level windowing system like PySide/Qt fails constantly.
** These install steps do get it working: http://nuitka.net/doc/user-manual.html#installation
*** Install Nuika, then the compiler, and Python of course. Try their hello.py example first as a baseline.
*py2exe (Windows) : http://www.py2exe.org/
*~PyInstaller (Windows, Linux, Unix\Irix) : http://www.pyinstaller.org/
*freeze : (Unix) : http://wiki.python.org/moin/Freeze
----
*[[Dependency Walker|http://www.dependencywalker.com/]] : Windows, for finding DLL dependency issues.
----
''gui2exe'' is a ui front end to many of the above applications:
*Main page: http://code.google.com/p/gui2exe/
*Tutorial: http://www.blog.pythonlibrary.org/2010/08/31/another-gui2exe-tutorial-build-a-binary-series/
http://docs.python.org/library/shutil.html
{{{
import shutil
# if the destination file already exists:
shutil.copyfile('c:/temp/from.txt', 'c:/temp/to.txt')
# if the destination file doesn't exist:
shutil.copy('c:/temp/from.txt', 'c:/temp/to.txt')
shutil.move('c:/temp/from.txt', 'c:/goo/from.txt')
}}}
{{{
d1 = [1,2,3,4]
d2 = ["a","b","c","d"]
d = dict(zip(d1, d2))
{1: 'a', 2: 'b', 3: 'c', 4: 'd'}
}}}
[[itertools.count()|http://docs.python.org/library/itertools.html#itertools.count]]
{{{
from itertools import count
for i in count(start=0, step=1):
# do something with i
}}}
The {{{count()}}} function could be authored like so (from the docs):
{{{
def count(start=0, step=1):
n = start
while True:
yield n
n += step
}}}
----
The below example is doing the same as above, but takes more lines (but no extra import).
{{{
i = 0
while True:
# do something with i
i += 1
}}}
As of Python 2.6:
Use the {{{fraction}}} module:
http://docs.python.org/library/fractions.html
From the docs:
{{{
from fractions import Fraction
Fraction(16, -10)
# Fraction(-8, 5)
Fraction(123)
# Fraction(123, 1)
Fraction()
# Fraction(0, 1)
Fraction('3/7')
# Fraction(3, 7)
# [40794 refs]
Fraction(' -3/7 ')
# Fraction(-3, 7)
Fraction('1.414213 \t\n')
# Fraction(1414213, 1000000)
Fraction('-.125')
# Fraction(-1, 8)
}}}
The [[zipfile|http://docs.python.org/library/zipfile.html]] module (among others).
Good notes here:
http://effbot.org/librarybook/zipfile.htm
Really simple example for making zips:
{{{
# zipper.py
import os
#import locale # Python 2 only
import zipfile
def main(files, zipname, storePaths=False):
"""
files : list : List of full file-paths to zip.
zipname : string : Full path of .zip file to save.
storePaths : bool : Default False. If storePaths == True, then full directory
paths are saved to each file in the zip. If False, then all files are
at root level of zip.
"""
# loc = locale.getdefaultlocale()[1] # Python2 only
zipper = zipfile.ZipFile(zipname, 'w', zipfile.ZIP_DEFLATED)
for f in files:
# f = f.encode(loc) # Python 2 only, breaks Python 3
if storePaths:
zipper.write(f)
else:
zipper.write(f, os.path.basename(f))
zipper.close()
for f in files:
print("\t",f)
print("Added above files to zip:", zipFileName)
}}}
{{{
import os
os.remove("c:/temp/foo.mel")
# or you can use:
os.unlink("c:/temp/foo.mel")
}}}
From [[here|http://stackoverflow.com/questions/354038/how-do-i-check-if-a-string-is-a-number-float-in-python]]:
{{{
def is_number(s):
try:
complex(s)
return True
except ValueError:
return False
print is_number("3.6")
True
print is_number("1b")
False
}}}
{{{mimetypes}}} bases its search of the extension it seems.
http://docs.python.org/library/mimetypes.html
There is also [[Python Magic|http://pypi.python.org/pypi/python-magic/]] which seems more robust, but its for Linux only.
{{{
import mimetypes
mimetypes.init()
j = "C:/temp/test.jpg"
t = "C:/temp/test.txt"
guessJ = mimetypes.guess_type(j)[0]
guessT = mimetypes.guess_type(t)[0]
print guessJ, guessT
# image/jpeg text/plain
}}}
Say you have two lists with the same number of elements, and you want to subtract each member from the corresponding other. How to easily do:
{{{
foo = [4, 4, 5]
goo = [1, 1, 5]
e = map(lambda x, y: x-y, foo, goo)
print e
# [3, 3, 0]
}}}
You can also do this on an arbitrary number of lists with a bit more work:
{{{
dataA = [1,2,3]
dataB = [-1,-2,-3]
dataC = [10,10,10]
listOfLists = [dataA, dataB, dataC]
def adder(*args):
return sum(args)
result = list(map(adder, *listOfLists))
print result
# [10, 10, 10]
}}}
By putting the asterix ({{{*}}}) in front of our variable name ({{{*listOfLists}}}), the map command will unpack the sub-lists from {{{listOfLists}}}, incrementally grab the same indicies from each, package them as a new list (first loop builds a list {{{[1, -1, 10]}}}, second loop is {{{[2, -2, 10]}}}, etc), pass them to {{{adder()}}}, which again, via the {{{*args}}} notation, unpacks that new list as individual elements, and processes them.
The above code could be simplified even more so as this:
{{{
result = list(map(lambda *x: sum(x), *listOfLists))
}}}
You override the {{{__nonzero__}}} method
http://docs.python.org/reference/datamodel.html#object.__nonzero__
{{{
class Foo(object):
def __init__(self, arg=None):
self.arg = arg
def __nonzero__(self):
if self.arg:
return True
else:
return False
f = Foo()
f.arg = "stuff"
if f:
print "good"
else:
print "bad"
# good
}}}
----
Also see:
*[[Operator Overloading]]
Good blog post on it here:
http://www.blog.pythonlibrary.org/2012/06/07/python-101-how-to-download-a-file/
Code snippets from that link:
{{{
# Python 2 code
import urllib
import urllib2
import requests
url = 'http://www.blog.pythonlibrary.org/wp-content/uploads/2012/06/wxDbViewer.zip'
print "downloading with urllib"
urllib.urlretrieve(url, "code.zip")
print "downloading with urllib2"
f = urllib2.urlopen(url)
data = f.read()
with open("code2.zip", "wb") as code:
code.write(data)
print "downloading with requests"
r = requests.get(url)
with open("code3.zip", "wb") as code:
code.write(r.content)
}}}
{{{
# Python 3 code
import urllib.request, urllib.parse, urllib.error
url = 'http://www.blog.pythonlibrary.org/wp-content/uploads/2012/06/wxDbViewer.zip'
print("downloading with urllib")
urllib.request.urlretrieve(url, "code.zip")
print("downloading with urllib2")
f = urllib.request.urlopen(url)
data = f.read()
with open("code2.zip", "wb") as code:
code.write(data)
}}}
I needed to create a class that had multiple inheritance, but that inheritance was based on a condition (what version some external software was). After some searching I found [[this post|http://stackoverflow.com/questions/9539052/python-dynamically-changing-base-classes-at-runtime-how-to]] that gave an example of how to update the base classes via the //classes// {{{__bases__}}} attr. I modified it to my own needs.
In the below example, {{{Foo}}} is our main class: It inherits from {{{Spam}}}. If some condition is met, I also want it to inherit from {{{Eggs}}}. The update is done in the {{{__init__}}} method: In the above example they modify the instance after the fact, but I want it to be taken care of automatically.
{{{
class Eggs(object):
def meth(self):
print "EGGS!"
class Spam(object):
pass
class Foo(Spam):
def __init__(self):
if True:
Foo.__bases__ = (Eggs, Spam)
print Foo.__bases__
}}}
{{{
f = Foo()
f.meth()
# (<class '__main__.Eggs'>, <class '__main__.Spam'>)
# EGGS!
}}}
[[pprint|http://docs.python.org/library/pprint.html]]
{{{
import pprint
myD = {"a":"A", 2:[1,2], "foo":{"subDict":[1,2,["a", 23]], "stuff":("my", "tupple", 52)}}
pprint.pprint(myD, width=32)
}}}
prints:
{{{
{2: [1, 2],
'a': 'A',
'foo': {'stuff': ('my',
'tupple',
52),
'subDict': [1,
2,
['a',
23]]}}
}}}
The built-in {{{operator}}} module has all the goodness that you need:
{{{
import operator
num = operator.add(10,5)
print num
# 15
}}}
This is closely tied to [[emulating numeric types|How can I have objects add themselves together? Subtract one another, etc?]] and 'operator overloading' in OOP.
A personal solution I use:
{{{
import os
import sys
def main(modulePath):
"""
Import the provided moduel, return the instance.
Parameters:
modulePath : string : The full path to the module on disk.
Return : module : The physically imported module, ready for use in your code.
"""
moduleDir = os.path.dirname(modulePath)
moduleName = os.path.splitext(os.path.split(modulePath)[-1])[0]
formatDir = moduleDir.lower().replace("\\", "/")
needsAdd = True
for path in sys.path:
if path.lower().replace("\\", "/") == formatDir:
needsAdd = False
break
if needsAdd:
sys.path.append(moduleDir)
module = None
exec('import %s as module'%moduleName)
return module
}}}
----
Available in Python 2.7 and //newer//, the {{{runpy.run_path()}}} function is available:
{{{
import runpy
modulePath = r'C:\path\to\my\module.py'
runpy.run_path(modulePath)
}}}
However that just runs the module: If you have a function in your module you'd want executed (like say, {{{main()}}}), you'd need to add this to the bottom of the module:
{{{
if __name__ == "<run_path>":
main()
}}}
http://docs.python.org/library/runpy.html
----
Found in [[this post|http://sayspy.blogspot.com/2011/07/how-to-import-module-from-just-file.html]], this code works in Python 3 (but not Python 2.x):
{{{
mod = exec(open('path', 'r').read(), __import__('sys').modules.setdefault('name', __import__('imp').new_module(name)).__dict__)
}}}
The above was considered a hack to simply do the whole thing on one line. But that blog post exposes other examples for doing this as well.
----
Presuming you're doing this in another module, you'll need to add its location to the path first (unless there is a fancier way).
In the below example, I define the full path to the module in a variable. I then extract just the path and module name. Add the path to {{{sys.path}}} then import the module name via {{{exec}}}.
{{{
import os
import sys
modulePath = r'c:\python\someModule.py'
moduleDir, moduleName = os.path.split(modulePath)
module, ext = os.path.splitext(moduleName)
sys.path.append(os.path.normpath(moduleDir))
exec('import %s as myModule'%module)
# presuming the module has a main function()
myModule.main()
}}}
----
Another option of course is simply add that modules path to the path, then import it:
{{{
import sys
sys.path.insert(0,"/path/to/module")
import module
}}}
----
Also see:
* [[Absolute module imports]]
I had an instance where I needed to execute a module that was outside my Python path (which launches a UI), and I didn't want to first add its directory as part of my Python path. Furthermore, the module in question was named illegally:
{{{
someModule.2.py
}}}
It had an extra {{{.2}}} in its name, which really upsets python on import statements.
To work around this, from a Python module, I called //to// Python at the system level (dos, Win7), to execute the module and launch the UI. The key was to use the system {{{chdir}}} to first put the system at that dir, //then// execute the module:
{{{
import os
import subprocess
module = r'C:\full\path\to\some\module\ofMine.py'
mpath, mfile = os.path.split(module)
# Two different open solutions:
subprocess.Popen("chdir %s & %s"%(mpath,mfile), shell=True)
# But this one locks out the executing module from completing until the ui is closed:
os.system("chdir %s & %s"%(mpath,mfile))
}}}
I had first tried executing this from a shell:
{{{
> python -m C:\full\path\to\some\module\ofMine.py
}}}
But I got this error:
{{{
C:\Python26\python.exe: Import by filename is not supported.
}}}
Which led me to the above solution.
@@If you are here@@, you probably just want to use {{{subprocess.run}}}, see notes here: [[Understanding subprocess: run and Popen]]
----
Older Docs:
Python 2.6 and //newer// ({{{os.popen}}} is deprecated). Use {{{subprocess}}}:
http://docs.python.org/library/subprocess.html
http://www.doughellmann.com/PyMOTW/subprocess/
{{{
import subprocess
}}}
----
Note: If you want to execute a system command and don't care about the result, you can use {{{subprocess.call}}}.
----
New example, taken from [[this post|http://www.logilab.org/blogentry/20469]]:
<<<
"{{{subprocess.Popen}}} takes a list of arguments as first parameter, which are passed as-is to the new process creation system call of your platform, and not interpreted by the shell:"
{{{
pipe = subprocess.Popen(['diff', '-u', appl_file, ref_file], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# These are file-type objects:
stdoutFile= pipe.stdout
stderrFile = pipel.stderr
}}}
"By now, you should have guessed that the shell=True parameter of subprocess.Popen should not be used unless you really really need it (and even them, I encourage you to question that need)."
<<<
----
''Note'': {{{subprocess.Popen}}} has a {{{wait()}}} method: If your code isn't pausing when you think it should, try the {{{wait()}}}.
A couple different ways:
Version A, using communicate()
http://docs.python.org/library/subprocess.html#subprocess.Popen.communicate
{{{
stdout, stderr = subprocess.Popen("system commands here", stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
print(stdout.decode())
print(stderr.decode())
}}}
{{{communicate()}}} returns a 2-index tuple: Index[0] is the stdout stream, and index[1] is the stderr stream. Python3 returns them as bytes.
----
Version B, using .stdout
http://docs.python.org/library/subprocess.html#subprocess.Popen.stdout
{{{
result = subprocess.Popen("system comands here", stdout=subprocess.PIPE).stdout
foo = [f.strip() for f in result.readlines() if f.strip() != ""]
for f in foo:
print f
}}}
This is similar to version A, but we're not using {{{communicate()}}}, and access the {{{stdout}}} stream directly. This returns a {{{file}}} object with the {{{stdout}}} data we care about, which we call {{{readlines()}}} method on, giving us a list, which we then clean up and return into the {{{foo}}} list via the {{{list comprehension}}}.
----
Sometimes, depending on what the system command is, you need to pass in the args {{{shell=True}}}:
{{{
# result as a tuple, (stdout, stdin):
result = subprocess.Popen("dir c:\\",
stdout=subprocess.PIPE,
shell=True).communicate()
# result as a file object:
result = subprocess.Popen("dir c:\\",
stdout=subprocess.PIPE,
shell=True).stdout
}}}
You also need to do this to launch certain external apps. If you don't care about capturing any return, it's a bit less code:
{{{
# launch notepad:
subprocess.Popen("start notepad", shell=True)
}}}
----
I've also ran into instance where I'd get this kind of error reported back:
{{{
WindowsError: (6, 'The handle is invalid')
}}}
If this is the case, I found the fix was to also pass in a pipe to the {{{stdin}}}
{{{
result = subprocess.Popen("dir c:\\",
stdout=subprocess.PIPE,
stdin=subprocess.PIPE,
shell=True).communicate()
}}}
----
//previous// to Python2.6:
{{{
import os
results = os.popen("system commands here").read().strip()
# returns list
# strip() is optional, but useful
}}}
http://docs.python.org/library/os.html#os.popen
----
Finally, you can use {{{os.system(command)}}}:
{{{
import os
ret = os.system('notepad')
print ret
# 0
}}}
{{{subprocess}}} is far superior however: {{{os.system}}} will always return {{{0}}} on windows machines, and will hang your program during execution (which may or may not be wanted.
[[exec|http://docs.python.org/ref/exec.html]] - statement
[[execfile|http://docs.python.org/lib/built-in-funcs.html]] - built-in function (search down in docs)
[[eval|http://docs.python.org/lib/built-in-funcs.html]] - built-in function (search down in docs)
----
Also see
*[[Statement]]
*[[Difference between exec and eval()]]
Crazy easy to get a list of all words in a text doc:
{{{
import re
txt = "c:/temp/words.txt"
words = re.findall(r'\w+', open(txt).read())
}}}
The {{{\w}}} is equal to {{{[^a-zA-Z0-9_]}}}, so it's extracting everything separated by a space. Special chars will be disregarded.
----
And using the [[collections.Counter|http://docs.python.org/2/library/collections.html#collections.Counter]] class, you can start to extract interesting stuff:
{{{
import re
from collections import Counter
txt = "c:/temp/words.txt"
words = re.findall(r'\w+', open(txt).read().lower())
common = Counter(words).most_common(4)
print common
# [('be', 3), ('it', 2), ('in', 2), ('to', 2)]
}}}
----
Also see:
*[[How can I find how many times a word show up in a text file?]]
http://docs.python.org/library/sys.html#sys.builtin_module_names
{{{
import sys
for m in sorted(sys.builtin_module_names):
print m
}}}
prints:
{{{
__builtin__
__main__
_ast
_bisect
_bytesio
_codecs
# etc...
}}}
Check out the {{{modulefinder}}} module:
http://docs.python.org/library/modulefinder.html
{{{
from modulefinder import ModuleFinder
finder = ModuleFinder()
finder.run_script('c:/path/to/my/module.py')
modules = sorted([name for name,mod in finder.modules.iteritems()])
print modules
}}}
{{{
['__main__', 'someOtherModuleA', 'anotherModuleB', 'etc']
}}}
As of Python 2.6:
http://docs.python.org/library/itertools.html#itertools.combinations
This gives every pair combo:
{{{
import itertools
items = 'ABCD'
combinations = list(itertools.combinations(items, 2))
print combinations
# [('A', 'B'), ('A', 'C'), ('A', 'D'), ('B', 'C'), ('B', 'D'), ('C', 'D')]
}}}
This will give every combo over any number of entries:
{{{
import itertools
items = ["a", "b", "c", "d", "e"]
allCombos = []
for i in range(2, len(items)):
combo = list(itertools.combinations(items, i))
allCombos.extend(combo)
for item in allCombos:
print item
('a', 'b')
('a', 'c')
('a', 'd')
('a', 'e')
('b', 'c')
('b', 'd')
('b', 'e')
('c', 'd')
('c', 'e')
('d', 'e')
('a', 'b', 'c')
('a', 'b', 'd')
('a', 'b', 'e')
('a', 'c', 'd')
('a', 'c', 'e')
('a', 'd', 'e')
('b', 'c', 'd')
('b', 'c', 'e')
('b', 'd', 'e')
('c', 'd', 'e')
('a', 'b', 'c', 'd')
('a', 'b', 'c', 'e')
('a', 'b', 'd', 'e')
('a', 'c', 'd', 'e')
('b', 'c', 'd', 'e')
}}}
Presume you have some module ({{{stuff.py}}}) that has classes defined at the top level of the module like so:
{{{
# stuff.py
class Spam(object):
pass
class Eggs(object):
pass
}}}
How can you query what those classes are in some other module?
{{{
# findStuff.py
import inspect
import stuff
for d in stuff.__dict__:
if inspect.isclass(stuff.__dict__[d]):
print stuff.__dict__[d].__name__, stuff.__dict__[d]
}}}
prints:
{{{
Spam <class 'stuff.Spam'>
Eggs <class 'stuff.Eggs'>
}}}
Everything in Python is an object: modules, functions, classes, instances of user defined classes, strings, etc. These objects can have [[attribute]]s which in turn can point to other objects. But some objects can be called to (if they support the {{{__call__}}} method) like functions, while others are treated like simple data members, and others could be modules themselves. The [[dir|http://docs.python.org/library/functions.html#dir]] function will give us a list of all attributes on an object. Then we just need to filter them via the [[callable|http://docs.python.org/library/functions.html#callable]] function.
The below example exposes a quick way to break them into two camps: Callable, or not.
From the below example, it lets you know you could do this:
{{{
print sys.argv # this isn't callable, but we can print its data
result = sys.callstats() # call to the function and capture the return
}}}
----
{{{
# let's inspect this module!
import types
import sys
call = []
data = []
module = []
# filter our results:
for d in sorted(dir(sys)):
if callable(eval('sys.%s'%d)):
call.append(d)
else:
if type(eval('sys.%s'%d)) is types.ModuleType:
module.append(d)
else:
data.append(d)
if len(data):
print "DATA:"
for d in data:
print "\t", d
if len(call):
print "CALLABLE:"
for c in call:
print "\t", c
if len(module):
print "MODULES:"
for d in module:
print "\t", d
}}}
prints (truncated):
{{{
DATA:
__doc__
__name__
__package__
__stderr__
__stdin__
__stdout__
api_version
argv
builtin_module_names
byteorder
...
CALLABLE:
__displayhook__
__excepthook__
_clear_type_cache
_current_frames
_getframe
call_tracing
callstats
displayhook
...
}}}
You could look at this fine blog pose here:
http://codeboje.de/findingemptydirectories/
Reposted here for prosperity. @@Thanks Kerim!@@
Verison A:
{{{
import os
from os.path import join, getsize
for root, dirs, files in os.walk('c:\\'):
if len(dirs)==0 and len(files)==0:
print root
}}}
Better version:
{{{
import os
from os.path import join, isfile
def walksub(dir):
isEmpty=True
subDirs=[]
for entry in os.listdir(dir):
if isfile(join(dir,entry))==True:
isEmpty = False
else:
subEmpty = walksub(join(dir, entry))
if subEmpty==True:
subDirs.append(join(dir, entry))
else:
isEmpty=False
if isEmpty == False:
for subDir in subDirs:
print subDir
return isEmpty
}}}
{{{
walksub('c:\\')
}}}
Search through every package in every path for .py modules. Search in each module for functions and classes.
{{{
"""
Create a dictionary. Each key is the path to a given module. The values are in
fact sub-dics, who's keys are 'classes' and 'functions', who's values are lists
of the found classes \ functions.
"""
import sys
import os
def getMFC():
"""
Get our Module, Function, and Classes
"""
data = {}
for p in sys.path:
for dirpath, dirnames, filenames in os.walk(p):
if '__init__.py' in filenames:
for f in filenames:
if f.endswith('.py'):
key = os.path.join(dirpath, f)
data[key] = {'functions':[], 'classes':[]}
# Crack open the file to inspect...
fh = open(key)
for line in fh:
if line.startswith('def'):
store = line.strip()[4:-1]
data[key]['functions'].append(store)
if line.startswith('class'):
store = line.strip()[6:-1]
data[key]['classes'].append(store)
return data
}}}
Example of some of the printed data:
{{{
import pprint # just for printing our results pretty :)
pprint.pprint(getMFC())
'(path truncated)/misc.py': {'classes': ['Set',
'Stack'],
'functions': ['flatten(tup)',
'mangle(name, klass)',
'set_filename(filename, tree)']},
}}}
Armed with that data, it's not too hard now to ''search inside of it'' for a certain keyword \ string:
{{{
def find(searchStr):
"""
Return a list of matching modules \ modules + functions & defs where
searchStr is found it. Case insensitive.
"""
data = getMFC()
results = []
searchStr = searchStr.lower()
for d in data:
if searchStr in d.lower():
results.append(d)
for func in data[d]['functions']:
if searchStr in func.lower():
results.append('%s - def %s'%(d, func))
for klass in data[d]['classes']:
if searchStr in klass.lower():
results.append('%s - class %s'%(d, klass))
pprint.pprint(results)
}}}
{{{
searchStr = 'color'
find(searchStr)
}}}
Example result (on a Mac):
{{{
['(path truncated...)/python2.6/site-packages/pygame/surfarray.py - def array_colorkey (surface)',
'(path truncated...)/python2.6/site-packages/pygame/examples/stars.py - def draw_stars(surface, stars, color)',
etc...
}}}
Wow, easy:
{{{
import re
from collections import Counter
count = Counter(re.findall(r'\w+', open(path).read()))["myWord"]
}}}
----
Also see:
*[[How can I extract all the words in a text document?]]
As of Python 2.6:
http://docs.python.org/library/os.path.html#os.path.relpath
{{{
import os
rel = os.path.relpath(r"c:\temp\foo\stuff", r"c:\temp")
print rel
# foo\stuff
}}}
Presuming you want to find all the text before (and including) the first underscore '_':
{{{
s = "prefix_stuff"
print s[0:s.find("_")+1]
# prefix_
}}}
If you don't want to include the underscore, remove the {{{+1}}}.
If there is no prefix, an empty string is returned.
Here is another technique:
{{{
s = "prefix_stuff"
print s.split('_')[0]
# prefix
}}}
This leaves off the 'split' character. Also, if there is no prefix to split, the whole string is returned.
This is a snipped taken and modified from here:
http://code.activestate.com/recipes/511491/
Works on Windows, pass in the drive letter to query.
{{{
import ctypes
def driveSpace(drive):
if not drive.endswith(":"):
drive += ":"
drive = unicode(drive)
freeuser = ctypes.c_int64()
total = ctypes.c_int64()
free = ctypes.c_int64()
ctypes.windll.kernel32.GetDiskFreeSpaceExW(drive,
ctypes.byref(freeuser),
ctypes.byref(total),
ctypes.byref(free))
spaceMB = freeuser.value / (1024 * 1024)
return spaceMB
}}}
I finally found a use for the {{{reduce}}} function! (plus some {{{lambda}}} action)
{{{
def average(numbers):
return reduce(lambda x, y: x + y, numbers) / len(numbers)
}}}
{{{
nums = [1, 2, 3, 4, 5.5]
print average(nums)
# 3.1
}}}
----
Another way with {{{reduce}}} and the {{{operator.add}}} function:
{{{
from operator import add
def average(numbers):
return reduce(add, numbers) / len(numbers)
}}}
{{{
numbers = [float(n) for n in range(1,10)]
print average(numbers)
# 5.0
}}}
----
Another way just using {{{sum}}}, and converting the passed in argument to a list:
{{{
def average(*numbers):
return sum(numbers)/len(numbers)
}}}
{{{
print average(1,2,3,4,5.5)
# 3.1
}}}
Copied directly from [[this recipe|http://code.activestate.com/recipes/578422/]] over at Activestate. By Oren Tirosh:
<<<
This is a quick one-liner to produce the filename and line number of the caller of the current function.
{{{
'{0.f_code.co_filename}:{0.f_lineno}'.format(sys._getframe(1))
}}}
This is useful for debugging and logging. It also nicely demonstrates the attribute access feature of the {{{.format()}}} method format string. If you wrap it in a function change the argument to {{{_getframe()}}} to {{{2}}}. Add {{{'{0.f_code.co_name}'}}} to the format string to get the name of function containing the call site.
<<<
My own warning:
@@NOTE:@@ {{{sys._geframe()}}} is a {{{CPython}}} implementation detail: the leading underscore is telling you this is behind the scenes magic, and you shouldn't play with it, because it could change in future versions, or not be available in other Python implementations. Use at your own risk...
Presuming you have a module with globals, and a function in the module... given the module itself, how can you find its global scope?
All function objects have a variety of attributes that can be accessed. One of which is {{{func_globals}}}, which is from the docs: "A reference to the dictionary that holds the function’s global variables — the global namespace of the module in which the function was defined."
{{{
# someModule.py
G = "I'm a global!"
def spam():
pass
def main():
funcGlobals = spam.func_globals
for k in funcGlobals:
print k, funcGlobals[k]
}}}
Docs [[here|http://docs.python.org/reference/datamodel.html#the-standard-type-hierarchy]] under the 'Callable types' section.
This is something I'd been trying to figure out for a long time: Given a variable that points to an object, how can you find the string that is the variable name? Not that I have any application for this, but I like to see if things are possible. Based on all my question asking on the forums and whatnot, the answer was always "no, you can't do this". Well, based on the below blog post, it looks like you can ;)
The one danger is that it uses {{{sys._getframe()}}}, which as you can tell by the leading underscore is considered private, and could change with future versions of Python, or different implementations.
http://docs.python.org/library/gc.html
http://pythonic.pocoo.org/2009/5/30/finding-objects-names
{{{
import gc, sys
def find_names(obj):
frame = sys._getframe()
for frame in iter(lambda: frame.f_back, None):
frame.f_locals
result = []
for referrer in gc.get_referrers(obj):
if isinstance(referrer, dict):
for k, v in referrer.iteritems():
if v is obj:
result.append(k)
return result
foo = []
def demo():
bar = foo
print find_names(bar)
demo()
# ['bar', 'foo']
}}}
I also found this blog post that does something very similar:
http://posted-stuff.blogspot.com/2010/01/locating-instances-of-python-classes.html
----
Good overview of the {{{gc}}} module:
http://www.doughellmann.com/PyMOTW/gc/
Variable names point to objects. A single object can be pointed to by multiple variables. How can you query how many pointers a given object has?
{{{
import sys
# define an list object [1,2,3], and assign it to variable foo
foo = [1,2,3]
assign list object [1,2,3] to variable goo
goo = foo
# how many pointers does list object [1,2,3] have to it?
print sys.getrefcount(foo)
# 3
}}}
I'm guessing the '3' means that the {{{sys.getrefcount}}} also has a pointer to it too.
How many pointers does the object '1' have to it?
{{{
print sys.getrefcount(1)
# 577
}}}
577 pointers on my machine at least ;)
A solution I came up with:
{{{
def stringIntersect(leftSide, rightSide):
"""
Find the overlap characters of two strings. The search is done case insensitive,
to help out with path names.
Parameters:
leftSide: string : The 'left' side of the string to compare
rightSide : string : The 'right' side of the string to compare.
Return : string : The parts where the leftSide overlaps the rightSide.
"""
results = ""
for char in rightSide:
check = results+char
if check.lower() in leftSide.lower():
results = check
continue
return results
leftSide = "c:/temp/path/to"
rightSide = "/Path/To/some/random/file.txt"
print stringIntersect(leftSide, rightSide)
# /Path/To
}}}
{{{
def precentageBetween(low, val, high):
if low > high:
# swap low for high if reversed:
low, high = high, low
return float(val - low) / float(high - low)
low = -10
high = 20
val = 5
print precentageBetween(low, val, high)
# 0.5
}}}
----
Also see:
*[[How do I lerp?]]
Found a lot of solutions online, this was the shortest one:
{{{
import locale
locale.setlocale(locale.LC_ALL, "")
print locale.format('%d', 12345, True)
# 12,345
}}}
http://docs.python.org/library/locale.html#locale.format
!New Solution
From here: https://stackoverflow.com/questions/477486/how-to-use-a-decimal-range-step-value
{{{
step = .1
maxVal = 1.0
numSteps = maxVal/step
assert numSteps == float(int(numSteps)), "Please provide a step value that can be cleanly divided into %s"%maxVal
stepVals = [ round(x*step,2) for x in range(0, int(numSteps)) ] + [maxVal]
print stepVals
[0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]
}}}
!Old Solution
The [[range|http://docs.python.org/library/functions.html#range]] function returns a list of integers. But what if you want to generate a range of floats evenly spaced apart by some value?
[[itertools.count|http://docs.python.org/library/itertools.html#itertools.count]] can help with this, but only if you're in Python 2.7 or newer. What about older?
Using part of their example, this is what I came up with:
{{{
def floatrange(end, start=0, step=1.0):
def count(cstart, cstep):
n = cstart
while True:
yield n
n += cstep
result = []
counter = count(start, step)
val = start
while (val+step) <= end:
val = float(counter.next())
result.append(val)
return result
}}}
{{{
foo = floatrange(5, start=1.5, step=.25)
print foo
[1.5, 1.75, 2.0, 2.25, 2.5, 2.75, 3.0, 3.25, 3.5, 3.75, 4.0, 4.25, 4.5, 4.75, 5.0]
}}}
It will return a list including every float value in-between and including start and end, based on the step size.
Pretend you have a min\max value, and want to generate an evenly spaced list of numbers between them, including them:
{{{
def getEventlySpaced(minVal, maxVal, numItems):
rng = maxVal-minVal
step = float(rng)/(numItems-1)
vals = [minVal]
for i in range(1,numItems-1):
vals.append(step*i+minVal)
vals.append(maxVal)
return vals
}}}
{{{
numItems = 5
minVal = 4
maxVal = 84
spaced = getEventlySpaced(minVal, maxVal, numItems)
print spaced
# [4, 24.0, 44.0, 64.0, 84]
}}}
The [[uuid|http://docs.python.org/2/library/uuid.html]] module ([[Universally Unique Identifier|http://en.wikipedia.org/wiki/UUID]]) seems to work pretty well.
From their [[examples|http://docs.python.org/2/library/uuid.html#example]] section, generate a random uid:
{{{
import uuid
uid = uuid.uuid4()
# 146ad84d-d17b-4502-8958-7bd367662cca
}}}
{{{os.environ}}} returns a [[Dictionary|DICTIONARY]]
Note: The values provided are a combination of both user and system env vars on windows.
{{{
import os
for key in os.environ:
print key + " : " + os.environ[key]
}}}
Also see:
*[[How can I query the value of an Environment Variable?]]
*[[How can I set an environment variable?]]
{{{dir}}} queries all the [[attributes|attribute]] (both variables, and functions) in the namespace being requested.
{{{
for thingy in dir(open):
print thingy
__call__
__class__
__cmp__
__delattr__
__doc__
__getattribute__
__hash__
__init__
__module__
__name__
__new__
__reduce__
__reduce_ex__
__repr__
__self__
__setattr__
__str__
}}}
Also see, for a comparison:
*[[How can I get a list of an object's attributes and methods?]]
Thanks to my bud Demetrius Leal on the tip with {{{netstat}}}:
On a Windows system, you can use {{{subprocess.Popen}}} to run the system {{{netstat}}} command. It returns a file-object which you can then parse:
{{{
import subprocess
pipe = subprocess.Popen(['netstat', '-ab'], stdout=subprocess.PIPE)
for line in pipe.stdout:
print line.strip()
}}}
{{{-a}}} : Displays all connections and listening ports.
{{{-b}}} : Displays the executable involved in creating each connection or listening port.
prints stuff like:
{{{
Active Connections
Proto Local Address Foreign Address State
TCP 0.0.0.0:235 username:0 LISTENING
RpcSs
[svchost.exe]
TCP 0.0.0.0:545 username:0 LISTENING
Can not obtain ownership information
TCP 0.0.0.0:4071 username:0 LISTENING
[javaw.exe]
...
}}}
Maybe there's a more built-in \ non-os specific way?
On ''Windows'', you can easily acces this via the {{{tasklist}}} system command:
{{{
import subprocess
output = subprocess.Popen(['tasklist'], stdout=subprocess.PIPE).stdout
for line in output:
print line.strip()
}}}
{{{
Image Name PID Session Name Session# Mem Usage
========================= ======== ================ =========== ============
System Idle Process 0 Services 0 24 K
System 4 Services 0 38,204 K
smss.exe 312 Services 0 1,356 K
csrss.exe 412 Services 0 6,076 K
etc...
}}}
You can also filter the result by passing args to the {{{tasklist}}} command:
{{{
import subprocess
output = subprocess.Popen(['tasklist', '/FI', 'IMAGENAME eq svcHost.exe'], stdout=subprocess.PIPE).stdout
for line in output:
print line.strip()
}}}
{{{
Image Name PID Session Name Session# Mem Usage
========================= ======== ================ =========== ============
svchost.exe 692 Services 0 12,284 K
svchost.exe 840 Services 0 13,968 K
svchost.exe 940 Services 0 20,796 K
etc...
}}}
Here's a more robust solution that turns all this data into a list of Python dicts, with each dict representing a specific process:
{{{
import subprocess
def getTaskData(searchStr=None):
"""
Windows only: Uses the tasklist dos cmd.
Based on all running processes, returns a list of dicts: Each dict has these keys:
"Image Name", "PID", "Session Name", "Session#", "Mem Usage", "Status",
"User Name", "CPU Time", "Window Title".
Optionally the user can pass in a search string, which will be used as a filter
on the "Image Name" (executable name).
"""
output = None
if searchStr:
output = subprocess.Popen(['tasklist', '/FO', 'LIST', '/V', '/FI', 'IMAGENAME eq python*'],
stdout=subprocess.PIPE).stdout
else:
output = subprocess.Popen(['tasklist', '/FO', 'LIST'],
stdout=subprocess.PIPE).stdout
data = []
appender = {}
for line in output:
stripped = line.strip()
if len(stripped) == 0 and len(appender):
data.append(appender)
appender = {}
continue
kv = [item.strip() for item in line.split(": ")]
if kv > 2:
# Some of our 'values' have the ": " string in them, so we need to
# rebuild that data after being split:
k = kv.pop(0)
v = ': '.join(kv)
kv = [k,v]
if kv[1] != '':
appender[kv[0]] = kv[1]
if not len(data):
data.append(appender)
return data
}}}
----
If you're looking for a way more directly authored in Python, check out this blog post:
http://www.blog.pythonlibrary.org/2010/10/03/how-to-find-and-list-all-running-processes-with-python/
{{{dir}}} queries all the attributes (both variables, and functions) in the namespace being requested.
make a file object f
{{{
f = open("c:/temp/foo.txt")
}}}
Now, query the *objects* [[methods|Method]] and [[attributes|attribute]]:
{{{
for thingy in dir(f):
print thingy
__class__
__delattr__
__doc__
__enter__
__exit__
__getattribute__
__hash__
__init__
__iter__
__new__
__reduce__
__reduce_ex__
__repr__
__setattr__
__str__
close
closed
encoding
fileno
flush
isatty
mode
name
newlines
next
read
readinto
readline
readlines
seek
softspace
tell
truncate
write
writelines
xreadlines
}}}
Also see, for a comparison:
*[[How can I get a list of a function's attributes and methods?]]
{{{
import glob
glob.glob("c:\\temp\\*.txt")
}}}
Also see:
*[[How can I get a list of files from a directory?]]
{{{
import os
files = os.listdir(myDir)
}}}
However, this will list subdirs as well including the files (leaf names only).
----
{{{
import os
files = os.walk(myDir).next()[2]
}}}
or
{{{
from glob import glob
files = glob(myDir+"/*.*")
}}}
These will list only files.
----
Also see:
*[[How can I get a list of files from a directory, based on a wildcard?]]
Python comes equipped with two functions: {{{locals()}}} and {{{globals()}}}. They are //dictionaries//.
To get a printable list:
{{{
for key in globals():
print key + " : " + str(globals()[key])
}}}
Remember, locals are the current function scope that you're in, and globals is the scope of the module.
{{{LEGB}}} -> ''L''ocal (function) -> ''E''nclosing (function), ''G''lobal (module), '''B''uiltin'.
{{{
import os
walker = os.walk(r"c:\temp")
subdirList = walker.next()[1]
print subdirList
# ['subDirA', 'subDirB']
}}}
{{{os.walk}}} returns a generator object. Each time you run it, it returns another level of subdirs etc. So the first time you run it using it's {{{.next}}} method, you capture the 2nd index (1) in the list, which his the list of subdirs. The first index (0) is the current dir, and the 3rd index (2) is the list of files in the current dir.
In the below example, we get a string representing the previous version of a given depot file from Perforce.
An interesting thing to note: {{{p4.run('print')}}} executes //much faster// than {{{p4.run_print()}}}.
{{{
from P4 import P4
p4 = P4()
p4.connect()
depotFile = "//myDepot/path/to/my/file.txt"
depotInfo = p4.run("fstat", depotFile)
headRev = int(depotInfo[0]["headRev"])
prevRev = headRev-1
oldRevData = p4.run('print', "-q", ['%s#%s'%(depotFile,prevRev)])
oldRevStr = oldRevData[1]
}}}
{{{
import os
startPaths = ['c:/temp', 'c/foo']
for sp in startPaths:
print os.path.normpath(sp)
for dirpath, dirnames, filenames in os.walk(sp):
for dir in dirnames:
name = os.path.join(dirpath, dir)
print os.path.normpath(name)
}}}
Also see:
*[[How can I recursively search directories and files, for something in a file?]]
*[[How can I search for files in directories faster than os.walk?]]
{{{
import socket
help(socket)
}}}
Say you make a custom class, and you want Python's {{{set}}} function / class to work on it correctly: How to do? I've read you need at minimum to implement {{{__eq__}}} & {{{__ne__}}}, but I've also need to implement {{{__hash__}}}.
In this example object, it has some valid string name we can test against for such things, but any testable type could be used.
{{{
class Spam(object):
def __eq__(self, other):
if str(self) == str(other):
return True
else:
return False
def __ne__(self, other):
if str(self) != str(other):
return True
else:
return False
def __hash__(self):
return hash(str(self))
def __str__(self):
return str("insert some string logic here")
}}}
Now you can do things like {{{set.union}}} or see if it's {{{in}}} a set.
Given a number like {{{2.32525}}}, how can I find just the {{{.32525}}} part?
{{{
import re
num = 2.32525
print num - int(num)
print float('0.%s'%str(num).split('.')[-1])
print float('0.%s'%re.findall('[0-9]+$', str(num))[0])
}}}
{{{
0.32525
0.32525
0.32525
}}}
But none of these seem very elegant... there //must be a better way!//
Modify the Python [[environment variable|What are Python-specific Environment Variables?]] {{{PYTHONSTARTUP}}} to the name of a readable file: the Python commands in that file are executed before the first prompt is displayed in interactive mode.
Also see : [[Using the sitecustomize & usercustomize modules]]
In Windows:
{{{
from win32com.client import Dispatch
# Open Photoshop
photoshop = Dispatch("Photoshop.Application")
# Open a file
document = photoshop.Open("c:/temp/tempfile.bmp")
# Rotate it:
document.Rotate(45)
# insert additional code #
}}}
You'll need to have the Win32 Extensions package installed to access {{{win32com}}}:
*http://sourceforge.net/projects/pywin32/
A good blog post:
*http://techarttiki.blogspot.com/2008/08/photoshop-scripting-with-python.html
A list of scripts to give you an idea of how to author your own:
*http://morris-photographics.com/photoshop/scripts/
You can find official documentation here:
*http://www.adobe.com/devnet/photoshop/scripting.html
I recommend the "~VisualBasic" reference for the applicable version of Photoshop you're running: The syntax of the API more closely matches the Python version.
----
There are many ''classes'' in the API that don't inherit from the {{{Application}}} object. For example, when doing a {{{Document.SaveAs()}}}, you need to pass in an object that represents the file-type you want to save. If you wanted to save a a targa (tga) file, you'd need an instance of a {{{TargaSaveOptions}}} object. How can you get this type of object ? Just like so:
{{{
# Say you want to save as a targa:
tgaSaveOptions = win32com.client.Dispatch("Photoshop.TargaSaveOptions")
document.SaveAs(pathToFile, tgaSaveOptions)
}}}
''Constants'' are another story: Authoring code via the native {{{JavaScript}}} \ {{{VisualBasic}}} \ {{{AppleScript}}} interfaces exposes theses constants automatically. I have yet to get access to them via Python. Via [[this page|http://docs.activestate.com/activepython/2.4/pywin32/html/com/win32com/HTML/QuickStartClientCom.html#UsingComConstants]] (and others), they describe this method of gaining access to constants:
<<<
Makepy automatically installs all generated constants from a type library in an object called {{{win32com.clients.constants}}}. You do not need to do anything special to make these constants work, other than create the object itself (ie, in the example above, the constants relating to Word would automatically be available after the {{{w=win32com.client.Dispatch("Word.Application")}}} statement.
For example, immediately after executing the code above, you could execute the following:
{{{
>>> import win32com.client
>>> w=win32com.client.Dispatch("Word.Application")
>>> w.WindowState = win32com.client.constants.wdWindowStateMinimize
}}}
and Word will Minimize.
<<<
However, this doesn't work for me using their example, or applying it to Photoshop: All I get are {{{AttributeErrors}}} since the {{{constants}}} type library appears to be empty. By running this code:
{{{
for d in dir(win32com.client.constants):
print d
}}}
All it prints is a few built-in special methods: No application-related constants at all.... :-S
The fix I've found is simply to find the enumerated value in the {{{VisualBasic}}} constant docs, and plug that in directly. It seems a big clunky, but does work.
----
''Some general notes as I use the API more:''
Object hierarchy:
*{{{Application}}} : The open Photoshop application.
**{{{Document}}} : An open File in Photoshop, part of the {{{Documents}}} collection object for the given parent.
***{{{ArtLayer}}} : one or more 'layers', part of the {{{ArtLayers}}} & {{{Layers}}} collections for its parent {{{Document}}}.
***{{{LayerSet}}} : one or more 'groups', part of the {{{LayerSets}}} & {{{Layers}}} collection object for the given parent. Can contain:
****{{{ArtLayer}}} : one or more 'layers', part of the {{{ArtLayers}}} & {{{Layers}}} collection for its parent {{{LayerSet}}}.
****{{{LayerSet}}} : This would be considered a sub-group, part of the {{{LayerSets}}} & {{{Layers}}} collection for it's parent {{{LayerSet}}}. This recursion can go forever with more child {{{LayerSet}}} and {{{ArtLayer}}} objects.
*****{{{...}}}
Notes on {{{Layers}}}, {{{LayerSets}}}, {{{ArtLayers}}}, & {{{LayerSet}}} and {{{ArtLayer}}} objects:
*{{{Layers}}}, {{{LayerSets}}}, and {{{ArtLayers}}} are container objects: They tell you, for the given parent object, what children they have of the given type. However, these collections aren't part of the hierarchy: They just help organize, and iterate over data.
*{{{Layers}}} is a collection of both {{{ArtLayer}}} and {{{LayerSet}}} objects, for the given parent object, which could be a parental {{{Document}}} (psd), or {{{LayerSet}}} (group). This is just a collection of data, it's not part of the tree.
*{{{LayerSets}}} : A collection of {{{LayerSet}}} objects (groups in Photoshop) for the given parent object, which could be a {{{Document}}} (psd), or it could be another {{{LayerSet}}} (since groups can live in groups, etc). This is just a collection of data, it's not part of the tree.
*{{{ArtLayers}}} : A collection of {{{ArtLayer}}} objects (layers in Photoshop) for the given parent object, which could be a {{{Document}}} (psd), or {{{LayerSet}}} (group in Photoshop). This is just a collection of data, it's not part of the tree.
*{{{LayerSet}}} : A 'group' in Photoshop. It can contain children {{{Layers}}}, {{{ArtLayers}}}, and {{{LayerSets}}} objects. It's parent is either a {{{Document}}} (if it is a root group) or another {{{LayerSet}}} object (if it is a subgroup).
*{{{ArtLayer}}} : A 'layer' in Photoshop. It has no children. It's parent in the docs is listed as only a {{{Document}}}, but since {{{ArtLayer}}} objects can live in {{{LayerSet}}} (group) objects, it seems like a {{{LayerSet}}} could be a parent as well.
So based on that info, this shows the child data for each object type:
*{{{Application}}}
**{{{Document}}} : One or more {{{Document}}} objects, referenced via the {{{Application.Documents}}} collection.
*{{{Document}}}:
**{{{LayerSet}}} : One or more {{{LayerSet}}} objects (groups in Photoshop), referenced via the {{{Document.LayerSets}}} collection, and part of the {{{Document.Layers}}} collection.
**{{{ArtLayer}}} : One or more {{{ArtLayer}}} objects (layer in Photoshop), referenced via the {{{Document.ArtLayers}}} collection, and part of the {{{Document.Layers}}} collection.
*{{{LayerSet}}}:
**{{{LayerSet}}} : One or more child {{{LayerSet}}} objects (sub-groups in Photoshop), referenced via the {{{LayerSet.LayerSets}}} collection, and part of the {{{LayerSet.Layers}}} collection.
**{{{ArtLayer}}} : One or more {{{ArtLayer}}} objects (layer in Photoshop), referenced via the {{{LayerSet.ArtLayers}}} collection, and part of the {{{LayerSet.Layers}}} collection.
*{{{ArtLayer}}} :
**Has no children, is a 'layer' in Photoshop. Referenced via the parent objects {{{ArtLayers}}} collection, and part of the parent objects {{{Layers}}} collection.
----
Useful methods and properties (attributes) for the API objects, based on the ~CS3 ~VisualBasic docs:
*{{{Application}}}
**Created via: {{{application = Dispatch("Photoshop.Application") }}}
**Properties:
***{{{ActiveDocument}}} : The active (top most in Photoshop) {{{Document}}} object. Read & write.
***{{{Documents}}} : Reference to its {{{Documents}}} object, which is an iterable collection of {{{Document}}} objects. Read-only.
***{{{Path}}} : String to the full path of the Photoshop executable. Read only.
***{{{Version}}} : String of the Photoshop version. Read only.
**Methods:
***{{{ExecuteAction}}} : Play an {{{ActionManager}}} event.
***{{{Open}}} : For the passed in string, open that image as a {{{Document}}}, and return the {{{Document}}}.
***{{{Quit}}}
***{{{Refresh}}} : Pause the script and refresh the application.
*{{{Documents}}} - iterable collection object
**Properties:
***{{{Application}}}, {{{Parent}}} : Reference to the {{{Application}}} object it belongs to.
***{{{Count}}} : Long : Number of {{{Document}}} objects in this {{{Documents}}} collection.
**Methods:
***{{{Add}}} : Create (and return) a new\empty {{{Document}}} object.
*{{{Document}}} - Single object
**New created via {{{Documents.Add()}}}. Opened via {{{Application.Open()}}}.
**Properties:
***{{{Application}}}, {{{Parent}}} : The {{{Application}}} object it belongs to. Read-only.
***{{{BackgroundLayer}}} : Reference to the background {{{ArtLayer}}}. Read-only.
***{{{FullName}}} : String, full path on disk to this document. Read-only.
***{{{Name}}} : String, just the leaf document name (name.ext), read-only.
***{{{Path}}} : String, just the path (no leaf file name) to the document, read-only.
***{{{Height}}} : Double, height of the document, read-only.
***{{{Width}}} : Double, width of the document, read-only.
***{{{Info}}} : Reference to this objects {{{DocumentInfo}}} object, metadata about the document. Read-only.
***{{{Layers}}} Reference to this objects {{{Layers}}} object, a collection of both {{{ArtLayer}}} and {{{LayerSet}}} objects. Could be imagined as a combination of the {{{ArtLayers}}} and {{{LayerSets}}} objects.
***{{{ArtLayers}}} : Reference to its {{{ArtLayers}}} object, which is an iterable collection of {{{ArtLayer}}} objects ('layers' in Photoshop).
***{{{LayerSets}}} : Reference to its {{{LayerSets}}} object, which is an iterable collection of {{{LayerSet}}} objects ('groups' in Photoshop).
***{{{Resolution}}} : Double, the documents resolution in pixels per inch.
***{{{Saved}}} : Bool, is it saved since the last change? Read-only.
**Methods:
***{{{Close}}} Close the document. It should be noted that unless this is the 'active document', Phothoshop will launch a confirm dialog, even if the {{{PsSaveOptions}}} arg {{{2}}} (close without dialog) is passed in.
***{{{Save}}} : Save the document (presuming it has already been saved before).
***{{{SaveAs}}} : Save a new document, or save an old one with a new path.
*{{{Layers}}} - iterable collection object (of Photoshop 'layers' and 'groups')
**Properties:
***{{{Application}}} : Reference to the {{{Application}}} object this belongs to. Read-only.
***{{{Count}}} : Long, number of {{{LayerSet}}} and {{{ArtLayer}}} objects in this collection. Read-only.
***{{{Parent}}} : Reference to the {{{Document}}} (or {{{LayerSet}}}) object this belongs to.
**Methods:
***{{{RemoveAll}}} : Removes all layers from this collection.
*{{{LayerSets}}} - iterable collection object (of Photoshop 'groups')
**Properties:
***{{{Application}}} : Reference to the {{{Application}}} object this belongs to. Read-only.
***{{{Count}}} : Long, number of {{{LayerSet}}} objects in this collection. Read-only.
***{{{Parent}}} : Reference to the {{{Document}}} (or {{{LayerSet}}}) object this belongs to.
**Methods:
***{{{Add}}} : Create (and return) a new {{{LayerSet}}} object
***{{{RemoveAll}}} : Removes all layers from this collection.
*{{{ArtLayers}}} - iterable collection object (of Photoshop 'layers')
**Properties:
***{{{Application}}} : Reference to the {{{Application}}} object this belongs to. Read-only.
***{{{Count}}} : Long, number of {{{ArtLayer}}} objects in this collection. Read-only.
***{{{Parent}}} : Reference to the {{{Document}}} object this belongs to.
**Methods:
***{{{Add}}} : Create (and return) a new {{{ArtLayer}}} object
***{{{RemoveAll}}} : Removes all layers from this collection.
*{{{LayerSet}}} - single object representation of a 'group' in Photoshop.
**Created via {{{LayerSets.Add()}}}
**Properties:
***{{{Application}}} : Reference to the {{{Application}}} object this belongs to. Read-only.
***{{{ArtLayers}}} : Reference to the {{{ArtLayers}}} container in this {{{LayerSet}}}. Read-only.
***{{{Bounds}}} : [minX, minY, maxX, maxY] : Bounding rectangle of the {{{LayerSet}}}. Read-only.
***{{{Layers}}} : Reference to the {{{Layers}}} container in this {{{LayerSet}}}. Read-only.
***{{{LayerSets}}} : Reference to the top layer {{{LayerSets}}} object in this document.
***{{{Name}}} : String name of this {{{LayerSet}}}, read-write.
***{{{Parent}}} : Either the parent {{{Document}}}, or {{{LayerSet}}} for this {{{LayerSet}}}. Read-only.
***{{{Visible}}} : Bool, read-write.
**Methods:
***{{{Delete}}} : Delete this {{{LayerSet}}}.
***{{{Duplicate}}} : Create a duplicate of this {{{LayerSet}}} (which it returns). Pass it a {{{ArtLayer}}} or {{{LayerSet}}} as the new parent.
***{{{Merge}}} : Merge the layerset, return a reference to the {{{ArtLayer}}} created by this method.
***{{{Move}}} : Move the {{{LayerSet}}} object to a new {{{Application}}}. Not sure how this works yet...
***{{{Resize}}} : Resize all layers in this {{{LayerSet}}}. Values passed in are percentages, range is 0->100.
***{{{Rotate}}} : Rotate clockwise by the given angle.
***{{{Translate}}} : Move this number of pixels. {{{Document}}} resolution must be set to 72 ppi first.
*{{{ArtLayer}}} - single object representation of a 'layer' in Photoshop.
**Created via {{{ArtLayers.Add()}}}
**Properties:
***{{{Application}}} : Reference to the {{{Application}}} object this belongs to. Read-only.
***{{{Bounds}}} : [minX, minY, maxX, maxY] : Bounding rectangle of the {{{LayerSet}}}. Read-only.
***{{{Name}}} : String name of this {{{LayerSet}}}, read-write.
***{{{Parent}}} : The parent {{{Document}}}, read-only.
***{{{Visible}}} : Bool, read-write.
**Methods:
***{{{Clear}}} : Cut the layer without moving it to the clipboard.
***{{{Copy}}} : Copy the layer to the clipboard.
***{{{Cut}}} : Cut the layer to the clipboard.
***{{{Delete}}} : Delete this {{{LayerSet}}}.
***{{{Duplicate}}} : Create a duplicate of this {{{LayerSet}}}. Pass it a {{{ArtLayer}}} or {{{LayerSet}}} as the new parent. Returns {{{ArtLayer}}}.
***{{{Merge}}} : Merge the layer down, return a reference to the {{{ArtLayer}}} this is merged into.
***{{{Move}}} : Move the {{{ArtLayer}}} object to a new {{{ArtLayer}}} or {{{LayerSet}}}.
***{{{Resize}}} : Resize all layers in this {{{LayerSet}}}. Values passed in are percentages, range is 0->100.
***{{{Rotate}}} : Rotate clockwise by the given angle.
***{{{Translate}}} : Move this number of pixels. {{{Document}}} resolution must be set to 72 ppi first.
The docs call this 'emulating numeric types':
http://docs.python.org/ref/numeric-types.html
See the docs for ALL of the various special methods you can define. This is Python's approach to 'operator overloading'.
These special methods' can be added to your class, that let you specify what happens when you add (for example) one object to another:
{{{
class MyObj(object):
num =0
def __init__(self, num):
self.num = num
def __add__(self, obj):
num = self.num + obj.num
return num
foo = MyObj(2)
goo = MyObj(3)
print foo + goo
# 5
}}}
''Other useful methods include:''
{{{__getitem__}}} is called when getting value from an object:
{{{
L = [1,2,3]
num = L[0]
# this is equal to:
num = L.__getitem__(0)
}}}
{{{__setitem__}}} is called when setting some value of an object:
{{{
L = [1,2,3]
L[0] = 10
# this is equal to:
L.__setitem__(0, 10)
}}}
So as you can see, in your own objects, you can modify the behavior of {{{__getitem__}}} and {{{__setitem__}}} to be whatever you need.
Found this code (only works on Windows):
http://code.activestate.com/recipes/578300-python-subprocess-hide-console-on-windows/
Why would you want to do this? One reason would be... if you have code that calls to many shells (one after the other), each one that pops open will steal focus from whatever app you're working in. This would prevent that from happening.
{{{
import sys
import subprocess
IS_WIN32 = 'win32' in str(sys.platform).lower()
def subprocess_call(*args, **kwargs):
#also works for Popen. It creates a new *hidden* window, so it will work in frozen apps (.exe).
if IS_WIN32:
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags = subprocess.CREATE_NEW_CONSOLE | subprocess.STARTF_USESHOWWINDOW
startupinfo.wShowWindow = subprocess.SW_HIDE
kwargs['startupinfo'] = startupinfo
retcode = subprocess.call(*args, **kwargs)
return retcode
}}}
Or more simply:
{{{
import sys
import subprocess
startupinfo = subprocess.STARTUPINFO()
if IS_WIN32:
startupinfo.dwFlags = subprocess.CREATE_NEW_CONSOLE | subprocess.STARTF_USESHOWWINDOW
startupinfo.wShowWindow = subprocess.SW_HIDE
results = subprocess.Popen(["myCmd", "someArg"], stdout=subprocess.PIPE, startupinfo=startupinfo).communicate()
}}}
http://docs.python.org/library/subprocess.html
This is a function I had made for my [[BubblePaint|http://www.akeric.com/blog/?p=601]] program in [[PyGame|http://www.pygame.org]]. In a nutshell, it will save the screen to a {{{png}}} image, and increment the filename with each image in the dir. This is a modification of a post over on my [[PyGame Wiki|http://pygamewiki.tiddlyspot.com/]].
{{{
import glob, os, re
def saveImage():
"""
Save the current image to the working directory of the program.
"""
currentImages = glob.glob(".\\*.png")
numList = [0]
for img in currentImages:
i = os.path.splitext(img)[0]
try:
num = re.findall('[0-9]+$', i)[0]
numList.append(int(num))
except IndexError:
pass
numList = sorted(numList)
newNum = numList[-1]+1
saveName = 'bubblePaint.%04d.png' % newNum
print "Saving %s" % saveName
pygame.image.save(screen, saveName)
}}}
Will save out files like this:
{{{
bubblePaint.0001.png
bubblePaint.0002.png
etc...
}}}
I thought it'd be cool to have some sort of "pickle inspector" window, where you could see the contents of saved pickle data. The below module is the result: You can drag&drop the pickle file onto this module's icon, and it'll print out the pickled data. That being said, it's pretty easy to break: If the pickled data requires any imports from modules that aren't part of your default Python path, it will fail. But I thought it was a good place to start.
{{{
# pickleInspector.py
import sys
import pickle
from pprint import pprint
def main(args):
"""
Print the values from the pickled data.
"""
if len(args) != 2:
return
with open(args[1]) as gerken:
loadedData = pickle.load(gerken)
pprint(loadedData)
if __name__ == "__main__":
try:
main(sys.argv)
except Exception, e:
print "EXCEPTION", e
finally:
raw_input("Press Enter to exit...")
}}}
{{{
# code...
raw_input("Press the enter key to exit.")
}}}
It's easy to make a {{{Tkinter}}} window, but I was often stumped on how to close them, if one is already open. Meaning: A window is open, the user re-clicks on the icon to create it: now there are two windows. Instead, I want the first one deleted, before the second one is created.
The below code will delete any application if it can match the given 'title' string in the data that the dos {{{tasklist}}} returns. Windows only, obviously. The idea is, before the window is created, this code is first ran to see if there is a pre-existing one, and if so, it kills it.
{{{
import subprocess
def killWindow(title):
"""
Windows only: Uses the tasklist & taskkill dos cmds.
Kill the window with the given title.
"""
output = subprocess.Popen(['tasklist', '/FO', 'TABLE', '/V', '/FI', 'IMAGENAME eq python*'],
stdout=subprocess.PIPE).stdout
for line in output:
strip = line.strip()
if title in strip:
# PID is the 2nd item in the list:
pid = strip.split()[1]
subprocess.Popen(['taskkill', '/PID', pid])
}}}
{{{
title = "My Tkinter Window"
killWindow(title)
}}}
Use the Windows {{{start}}} command.
{{{
import subprocess
myFile = "c:/path/to/any/file.extension"
subprocess.Popen(["start", myFile], stdout=subprocess.PIPE, shell=True)
}}}
{{{
# Windows only:
import os
os.startfile("notepad")
}}}
On Unix of Mac you'll need to use {{{subprocess}}} or {{{os.system}}}
----
Also see: [[How can I execute a system command, and capture the return?]]
{{{
# setup some lists for the below example:
words = ["one","two","three","four"]
numbers = [1,2,3,4]
foo = ["snarg", "nerf", "toos", "flurb"]
}}}
''If you have //more// than two lists'', you can use this '{{{for i in range}}}' example, or {{{enumerate}}} (they both print the same results):
{{{
for i in range(len(words)):
print words[i], numbers[i], foo[i]
for (offset,item) in enumerate(words):
print item, numbers[offset], foo[offset]
# one 1 snarg
# two 2 nerf
# three 3 toos
# four 4 flurb
}}}
These both require that all the lists //are the same length//. If they are not, you'll get an {{{IndexError}}}.
----
--''If you have exactly two lists''--: Update: I used to think that {{{map}}} and {{{zip}}} only worked on //two// lists, but in fact, they //do// work on multiple lists:
You can use the {{{map()}}} function, passing in {{{None}}} as its first argument (the first arg is a function to apply to each item in the list, so in this case we're not using that functionality). Or you can use the {{{zip()}}} function. These are much prettier than the previous example, --but they also are limited by only working on two lists.--
{{{
# setup some lists for all the below examples:
words = ["one","two","three"] # note the missing 'four'
numbers = [1,2,3,4]
foo = ["snarg", "nerf", "toos", "flurb"]
}}}
{{{map()}}}:
{{{
# Notice that all the map functions insert 'None' into the lists where
# there would be a missing list element:
# map version 1:
for w, n, f in map(None, words, numbers, foo):
print w, n, f
# one 1 snarg
# two 2 nerf
# three 3 toos
# None 4 flurb
# map version 2:
for thing in map(None, words, numbers, foo):
print thing
# ('one', 1, 'snarg')
# ('two', 2, 'nerf')
# ('three', 3, 'toos')
# (None, 4, 'flurb')
# map vresion 3: (similar to version 1 in result)
for thing in map(None, words, numbers, foo):
print thing[0], thing[1], thing[2]
# one 1 snarg
# two 2 nerf
# three 3 toos
# None 4 flurb
}}}
{{{zip()}}}:
{{{
# zip version 1:
for w, n, f in zip(words, numbers, foo):
print w, n, f
# one 1 snarg
# two 2 nerf
# three 3 toos
# Other zip examples behave the same as map, but simply
# truncate the results to the shortest list. No point in doing
# all the retyping here...
}}}
The main differences:
*{{{map()}}} will work on all indicies, even if one list is shorter than another (but, that could cause problems obviously). As you can see, it introduces {{{None}}} into the missing index.
*{{{zip()}}} works up until the length of the shortest list.
Both of them can handle the differences in list lengths //without// raising an exception, compared to the '{{{for i in range}}}' example which will.
----
Also see:
*The Python docs on looping techniques: http://docs.python.org/tut/node7.html#SECTION007600000000000000000
Python comes included with it's own {{{tkMessageBox}}} modal dialog, which you can embed in your apps:
{{{
import tkMessageBox
# somewhere inside your function...
result = tkMessageBox.askquestion("Message Title!", "Some Question!?!?", icon='warning')
if result == 'yes':
doYesFunc()
else:
doNoFunc()
}}}
http://effbot.org/tkinterbook/tkinter-standard-dialogs.htm
It has many different options\dialog types, the above link gives a nice overview.
If you're wondering: http://www.perforce.com/
!!!Via the Perforce [[API|Perforce access via Python]]:
[[P4 API Docs|http://www.perforce.com/perforce/doc.current/manuals/p4script/03_python.html#1116373]]
This will both create a changelist, and optionally add files to it. The file add system is terribly limited: It will only work on files already existing in P4, that aren't already open for edit. You'd need to write a more robust set of conditions to work with files that are to be added, files that live in another changelist, files that should be deleted, or files that someone else has checked out. But it gives you an idea for where to start...
Thanks to an email from Ross Kameny got me this code snippet:
{{{
import P4
def makeChangelist(description, files=[]):
"""
description : string : The changelist description
files : list : The files to edit. Default is an empty list.
"""
p4 = P4.P4()
p4.connect()
if files:
p4.run_edit(files)
changeList = p4.fetch_change()
changeList["Description"] = description
if files:
changeList["Files"] = files
results = p4.save_change(changeList)
changelistNum = int(results[0].split(' ')[1])
p4.disconnect()
return changelistNum
}}}
!!!Via calls to the system:
This just makes an empty changelist, doesn't add any files to it.
First, you need to generate a text file with the change info in it, and save it. Like {{{c:/temp/myChangelist.txt}}}:
{{{
Change: new
Description:
Enter description here, one line
}}}
Then in Python, call to P4 to create the changelist, then find the changelist number (to be used to add things to the list):
{{{
import os
p4changeReturn = os.popen("P4 change -i < c:/temp/myChangelist.txt").read().strip()
buffer = p4changeReturn.split(" ")
changelistNumber = buffer[1]
}}}
FYI: In Python 2.6 and newer, {{{popen}}} is depricated. Check notes on {{{subprocess}}} [[here|How can I execute a system command, and capture the return?]]
On Windows, it's pretty easy to make some nice beeping sounds with {{{winsound.Beep}}}:
http://docs.python.org/library/winsound.html
{{{
import winsound
for i in range(50, 5000, 10):
winsound.Beep(i, 25)
}}}
----
Blog post dealing with [[PyAudio|http://people.csail.mit.edu/hubert/pyaudio/]]:
http://davywybiral.blogspot.com/2010/09/procedural-music-with-pyaudio-and-numpy.html
----
Blog post about other Python implementations:
http://diagrammes-modernes.blogspot.com/2007/08/music-control-tools-python-based.html
----
[[Pyknon|https://github.com/kroger/pyknon]]
"Pyknon is a simple music library for Python hackers. With Pyknon you can generate Midi files quickly and reason about musical
proprieties."
----
There's also the builtin [[wave|http://docs.python.org/2/library/wave.html]] library that can read and write wav data, but I'm not sure if it can actually play it.
''pyexiv2''
http://tilloy.net/dev/pyexiv2/index.htm
----
Also see:
*http://www.exif.org/
Languages like Processing have [[functions|http://www.processing.org/reference/map_.html]] that will take a given value from one range and map it into another. I can't seem to find this in Python, but here's the code:
{{{
def valueRangeMap(val, origMin, origMax, newMin, newMax):
"""
Will remap val from the original range into the new range.
val : The value you are mapping.
origMin : The original minimum value that val should be greater than.
origMax : The original maximum value that val should be less than.
newMin : The new minimum value that val will be mapped into.
newMax : the new maximum value that val will be mapped into.
return : float : The newly mapped value.
"""
# Find the percentage val is between origMin and origMax:
percetVal = float(val - origMin) / float(origMax - origMin)
# Map into the new range:
mappedVal = (newMin+newMax)*percetVal
return mappedVal
print valueRangeMap(5, 0, 10, 10, 20)
# 15.0
}}}
{{{
import re
search = "/my/dir/is/mixed"
line = "lineData -- C:/my/Dir/is/MIXED/case --moreData"
print re.findall(search, line, re.IGNORECASE)
# ['/my/Dir/is/MIXED']
}}}
Or:
{{{
import re
search = "what"
names = ["abcd:whAt", "whaT", "goosE", "biud:WHAT"]
results = []
for name in names:
if re.findall(search, name, re.IGNORECASE):
results.append(name)
print results
# ['abcd:whAt', 'whaT', 'biud:WHAT']
}}}
I was designing a UI for a [[PyGame|http://www.pygame.org]] program I am working on, and needed a way to pass a value defining a "row height" into the functions that rendered my text to the screen. Since the UI could change, I didn't want to have to hard-code positions into each element, later to modify it and have to redo all the positions.
What I came up with was a simple class with a single usable attribute, called {{{val}}}. Through using [[properties|property]], I'm able to control how the attr behavies at time time its value is queried:
{{{
class Row(object):
# class to store the current row location in the UI
# Each time it is called, it will increment its value
def __init__(self, val):
self._val = 0
self.orig = val
@property
def val(self):
self._val = self._val + self.orig
return self._val
row = Row(16)
print row.val, row.val, row.val, row.val
# 16 32 48 64
}}}
Properties have getter, setter, and deleter methods, but the default is getter, which I used above. So as you can see, each time I call to print, it accesses the val property (via the getter), and updates the internal counter.
{{{
overlay.blit(bubble, (8, row.val))
overlay.blit(toggleText, (8, row.val))
overlay.blit(lmb, (8, row.val))
}}}
Rather than having to specify a {{{Y}}} value for the last arg of the tuple, I can simply pass in my object, and it passes out the current new position, based on how many times it was called before.
I have no doubt there is probably some slicker way in Python, but it's what I came up with on the spot :)
----
Also see:
*[[property]]
{{{_winreg}}} - Windows only (obviously)
*http://www.blog.pythonlibrary.org/2010/03/20/pythons-_winreg-editing-the-windows-registry/
See Python [[docs|http://docs.python.org/library/_winreg.html]]
The below function will offset the given item in the given list by the given offset. It will wrap the offset as well. Note this modifies the list in-place.
{{{
def offsetListItem(theList, theItem, theOffset, wrap=True):
"""
theList : The list to modify in-place.
theItem : element of the list to offset.
theOffset : int representing how much to offset, positive or negative.
"""
oldIndex = theList.index(theItem)
newindex = oldIndex+theOffset
if wrap:
if newindex > len(theList)-1:
newindex = 0
elif newindex < 0:
newindex = len(theList)-1
# Got this bit from:
# http://stackoverflow.com/questions/3173154/move-an-item-inside-a-list
theList.insert(newindex, theList.pop(oldIndex))
}}}
{{{
theList = ["a", "b", "c", "d"]
theItem = "a"
theOffset = 1
offsetListItem(theList, theItem, theOffset, wrap=True)
print theList
# ['b', 'a', 'c', 'd']
}}}
This will normalize values so they all ''fit'' between 0 and 1: The largets value becomes 1.0, and all other assume their relative values:
{{{
def normlizeVals(vals):
normalized = []
for val in vals:
normalized.append( (val-min(vals)) / (max(vals)-min(vals)) )
return normalized
}}}
{{{
vals = [.1, 20.3, 5.6, 15.3]
print normlizeVals(vals)
# [0.0, 1.0, 0.2722772277227723, 0.7524752475247526]
}}}
----
Another solution that will normalize them so they all ''add'' to 1.0:
{{{
def normlizeVals(vals):
return [float(val)/sum(vals) for val in vals]
normed = normlizeVals( [.1, 20.3, 5.6, 15.3] )
print normed, sum(normed)
# [0.002421307506053269, 0.49152542372881364, 0.13559322033898305, 0.37046004842615016] 1.0
}}}
HOWVER, based on Python's [[floating point|https://docs.python.org/3/tutorial/floatingpoint.html]] precision, these don't always add up exactly to 1.0
This function will 're-normalize' the weights, and //attempt// to solve for floating point rounding errors.
{{{
def normalizeWeights(weights) :
if sum(weights) == 1.0:
return weights
normed = [weight/sum(weights) for weight in weights]
normSum = sum(normed)
# Deal with floating point rounding errors
if normSum != 1.0:
minIndex = normed.index(min(normed))
normBuffer = normed[:]
normBuffer.pop(minIndex)
sumAllButMin = sum(normBuffer)
newMinVal = 1.0 - sumAllButMin
if newMinVal >= 0.0:
normed[minIndex] = newMinVal
else:
normed[minIndex] = 0.0
maxIndex = normed.index(max(normed))
normed[maxIndex] += newMinVal
return normed
}}}
What's really interesting is: If you check the summed values after this tool is ran, sometimes they //still// don't normalize to 1.0 : They're usually a very smaller value,like {{{.9999999999999999}}}.
Other notes:
* Python has a [[decimal|https://docs.python.org/3/library/decimal.html]] module that feels like it will help with this. And if I convert everything to {{{Decimal}}} classes and do the same work, it seems to be correct. However, when you convert them back to float for weight assignment, the imprecisions come back the exact same :(
* I've tried writing the above code using {{{numpy}}}, get the same results.
* I've tried rounding the numbers too: This makes the results worse across the board.
Couple different solutions:
{{{
import os
import subprocess
}}}
{{{
os.startffile("c:/temp") # Supports forwardslash on Windows
}}}
{{{
# Paths need to be backslashes on Windows when using os.system:
path = os.path.normpath("c:/path/to/my/file.txt")
if os.path.isfile(path):
# This will both open explorer, and select the file:
os.system('explorer /select, %s'%path.replace("/", "\\"))
if os.path.isdir(path):
os.system('explorer %s'%path)
}}}
{{{
subprocess.run(["explorer", "/select,", "c:\\temp\\myFile.txt"])
}}}
Solution from:
https://stackoverflow.com/questions/9319317/quick-and-easy-file-dialog-in-python
!Python 2:
{{{
import Tkinter, tkFileDialog
root = Tkinter.Tk()
root.withdraw()
file_path = tkFileDialog.askopenfilename()
}}}
!Python 3
{{{
import tkinter as tk
from tkinter import filedialog
root = tk.Tk()
root.withdraw()
file_path = filedialog.askopenfilename()
}}}
----
Also see:
https://pythonspot.com/tk-file-dialogs/
For examples to make directory browser and save-as dialog
{{{
import webbrowser
webbrowser.open_new("http://www.google.com")
}}}
Say you have to import a module, and that module has a function you just hate. You want to replace it with your own function, or get rid of it entirely. How? @@MONKEYPATCH@@
{{{
import sys
def myOverrideFunc(*args, **kwargs):
print "oh no you don't!"
module = sys.modules['path.to.some.module']
module.someDumbFunction = myOverrideFunc
}}}
Now, whenever someone calls to {{{/path/to/some/module.py}}} -> {{{someDumbFunction()}}}, they'll instead be calling to {{{myOverrideFunc()}}}.
Had an issue where I needed to change the behavior of a method //after// it's parental class was instance: I needed the original method code to run, //plus// my new code. To completely override it with something new is easy, to replace it with something that called to the original instance was a bit more tricky.
This is the solution I came up with:
{{{
class Spam:
def meth(self, val):
# A method we want to run, plus override later.
print "orig"
return val
def overrideMethod(inst):
# Store a copy of our original method on the instance,
# which we can call to in the override:
inst._meth = inst.meth
# Define the override method here:
def new_meth(val):
# Call to the original method:
origVal = inst._meth(val)
# Put any new override code in here:
print "override"
return origVal + val
# Install the override method on the instance:
inst.meth = new_meth
}}}
{{{
foo = Spam()
print foo.meth(5)
overrideMethod(foo)
print foo.meth(5)
}}}
{{{
orig
5
orig
override
10
}}}
----
Also see:
*[[Monkey-patch class instances]]
Presume you want to have 5-digit padding on a number:
{{{
someInt = 123
print str(someInt).zfill(5)
# 00123
}}}
After converting your {{{int}}} object to a {{{string}}} object, you can use the {{{string.zfill}}} method to generate the padding.
It's important that you work on {{{int}}}'s, and not {{{float}}}'s, since when converted to a {{{string}}}, the {{{float}}} decimal will just confuse {{{zfill()}}}
----
Another method, using [[string formatting|http://docs.python.org/library/stdtypes.html#string-formatting]]
{{{
for i in range(10):
print "image%05d.bmp" %(i)
}}}
{{{
image00000.bmp
image00001.bmp
image00002.bmp
image00003.bmp
image00004.bmp
# etc...
}}}
I was browsing the web for anything Python related, and ran across this page:
http://www.oreillynet.com/onlamp/blog/2007/02/simple_cpython_code_comparison.html
I modified the code to my needs, and here is an example:
{{{
import xml.etree.ElementTree as ET
import urllib
rssUrl = "http://pythonwiki.tiddlyspot.com/index.xml"
et = ET.parse(urllib.urlopen(rssUrl))
for elem in et.findall("//item"):
print elem.find("title").text
print "\t"+elem.find("link").text
}}}
In the example, we grab the .rss feed of this wiki, and print a list of subjects, and their permalinks.
Example of printing:
{{{
Accessing the Windows clipboard
http://pythonwiki.tiddlyspot.com#%5B%5BAccessing%20the%20Windows%20clipboard%5D%5D
list comprehension
http://pythonwiki.tiddlyspot.com#%5B%5Blist%20comprehension%5D%5D
How can I see if a directory exists, and if not, make one?
http://pythonwiki.tiddlyspot.com#%5B%5BHow%20can%20I%20see%20if%20a%20directory%20exists%2C%20and%20if%20not%2C%20make%20one%3F%5D%5D
etc...
}}}
Docs to:
*[[urllib|http://docs.python.org/library/urllib.html]]
*[[ElementTree|http://docs.python.org/library/xml.etree.elementtree.html]]
Here's an example using 'Windows Media Player' on my Win7 box:
{{{
import os
import subprocess
player = os.path.join(os.getenv("ProgramFiles(x86)"),
"Windows Media Player\wmplayer.exe")
vid = "C:/videos/myVideo.avi"
subprocess.Popen([player, vid])
}}}
Or, you can use the OS's default player for such a thing:
{{{
import os
vid = "C:/videos/myVideo.avi"
os.startfile(vid)
}}}
On Windows:
http://docs.python.org/library/winsound.html
{{{
import winsound
winsound.PlaySound('c:/temp/myWav.wav', winsound.SND_ALIAS)
}}}
----
There's also the builtin [[wave|http://docs.python.org/2/library/wave.html]] library that can read and write wav data, but I'm not sure if it can actually play it.
It's nice to know all the data associated with an object at a glance. Thanks to our friends the {{{dir}}} and {{{eval}}} functions, we can query all the attrs on an object, then 'evaluate' their values:
{{{
class Spam(object):
"""Super dooper Spam object"""
def __init__(self):
self.d = {"some":"dictionary value"}
self.word = "eggs!"
def attrPrinter(obj):
for attr in sorted(dir(obj)):
print attr, " : ", eval('obj.%s'%attr)
meat = Spam()
attrPrinter(meat)
}}}
{{{
__class__ : <class '__main__.Spam'>
__delattr__ : <method-wrapper '__delattr__' of Spam object at 0x00D00810>
__dict__ : {'word': 'eggs!', 'd': {'some': 'dictionary value'}}
__doc__ : Super dooper Spam object
__format__ : <built-in method __format__ of Spam object at 0x00D00810>
__getattribute__ : <method-wrapper '__getattribute__' of Spam object at 0x00D00810>
__hash__ : <method-wrapper '__hash__' of Spam object at 0x00D00810>
__init__ : <bound method Spam.__init__ of <__main__.Spam object at 0x00D00810>>
__module__ : __main__
__new__ : <built-in method __new__ of type object at 0x1E1CB570>
__reduce__ : <built-in method __reduce__ of Spam object at 0x00D00810>
__reduce_ex__ : <built-in method __reduce_ex__ of Spam object at 0x00D00810>
__repr__ : <method-wrapper '__repr__' of Spam object at 0x00D00810>
__setattr__ : <method-wrapper '__setattr__' of Spam object at 0x00D00810>
__sizeof__ : <built-in method __sizeof__ of Spam object at 0x00D00810>
__str__ : <method-wrapper '__str__' of Spam object at 0x00D00810>
__subclasshook__ : <built-in method __subclasshook__ of type object at 0x011860C8>
__weakref__ : None
d : {'some': 'dictionary value'}
word : eggs!
}}}
Many custom Python P4 tools rely on certain P4 environment variables to work correctly. On new machines, they haven't been setup yet. Here's now to do it via the P4V window:
Connection -> Environment Settings... : When that dialog opens, make sure that the 'Use current connection for environment settings' box is checked, and hit "OK" : It will promote these P4 env vars so that P4 can see them at the commandline in a shell:
{{{
> p4 set
}}}
* {{{P4PORT}}} ( aka, the 'server')
* {{{P4CLIENT}}} (aka, the 'workspace')
* {{{P4USER}}}
You can confirm this worked by opening a Windows cmd shell, and typing:
{{{
p4 set
}}}
which should show you something like:
{{{
P4CLIENT=my.name_someClientName (set)
P4PORT=server:someNumber (set)
P4USER=my.name (set)
}}}
----
Also see
* [[Perforce access via Python]]
{{{
import sys
path = sys.path
}}}
{{{sys.path}}} is made up of this data (in order I believe):
#Home dir of the program (the location of the top-level module that was executed).
#{{{PYTHONPATH}}} dirs, if any are set.
#The Standard Library dirs: {{{<drive>:\Python<ver>\Lib\*}}}
#Dirs defined by any {{{.pth}}} files (if they exist).
The result of these four become what {{{sys.path}}} returns.
{{{
import sys
print sys.version
# 2.5.1 (r251:54863, Jun 5 2007, 22:56:07) [MSC v.1400 32 bit (Intel)]
print sys.version_info
# (2, 5, 1, 'final', 0)
}}}
{{{sys.version}}} prints out a nice happy string, while {{{sys.version_info}}} returns a tupple with the corresponding ingredients.
Via {{{inspect.getargspec}}}
http://docs.python.org/library/inspect.html#inspect.getargspec
----
This example shows you the values after the fact:
{{{
import inspect
def spam(paramA, paramB, paramC='52', pamarD=[1,2,3]):
pass
argspec = inspect.getargspec(spam)
print argspec
print argspec.args
}}}
{{{
ArgSpec(args=['paramA', 'paramB', 'paramC', 'pamarD'], varargs=None, keywords=None, defaults=('52', [1, 2, 3]))
['paramA', 'paramB', 'paramC', 'pamarD']
}}}
It returns a {{{named tuple}}}
http://docs.python.org/glossary.html#term-named-tuple
----
But you can also query inside the function itself:
{{{
import inspect
def spam(paramA, paramB, paramC='52', pamarD=[1,2,3]):
argspec = inspect.getargspec(spam)
print "My Args Are:"
for item in argspec.args:
exec 'argVal = %s'%item
print item, "=", argVal
spam("a", "b")
My Args Are:
paramA = a
paramB = b
paramC = 52
pamarD = [1, 2, 3]
}}}
The [[socket|http://docs.python.org/library/socket.html]] module can be used to easily query the 'hostname', the 'fully qualified domain name', and the IP address.
{{{
import socket
import maya.cmds as cmds
print socket.gethostname()
print socket.getfqdn(socket.gethostname())
print socket.gethostbyname(socket.gethostname())
}}}
{{{
wCat
wCat.domainName.com
10.111.3.120
}}}
----
Also see:
*[[How can I query a users name? Their 'profile' directory?]]
In Windows:
{{{
name = os.getenv('USERNAME')
profile = os.getenv('USERPROFILE')
}}}
On Vista:
{{{
wCat
C:\Users\wCat
}}}
----
Also see:
*[[How can I query a users host name, domain name, IP address?]]
Perforce generally tracks three paths to a file:
* {{{depotFile}}}
* {{{clientFile}}}
* {{{path}}} (the local path on your HD).
To query this data, via the commandline:
{{{
p4 -ztag where thePath
}}}
Where 'somePathToAFile' can be a depotFile path, clientFile path, or local HD path.
Some examples of the paths:
* {{{depotFile}}} : {{{//my-depot/rootDir/pathA/pathB/file.txt}}}
* {{{clientFile}}}: {{{//my.name_depot/rootDir/pathA/pathB/file.txt}}}
* {{{path}}} : {{{c:\projectRoot\rootDir\pathA\pathB\file.txt}}}
You can query all this in Python via:
{{{
pathInfo = subprocess.Popen(["p4", "-ztag", "where", thePath], stdout=subprocess.PIPE).communicate()
}}}
And then parse the results of {{{pathInfo[0]}}}.
http://en.wikipedia.org/wiki/Newline
----
*Carriage Return : {{{\r}}}
*Line Feed : {{{\n}}}
----
*DOS : CR+LF : {{{\r\n}}}
*UNIX \ LINUX : LF : {{{\n}}}
----
DOS & UNIX\LINUX use different type of line endings on their files. Can check for this a few different ways:
----
Per line, print if it's a Unix or Dos newline:
{{{
f = "c:/temp/temp.txt"
with open(f) as myfile:
for line in myfile:
if line.find(r"\r\n") == -1:
print "DOS", line.rstrip()
elif line.find(r"\n") == -1:
print "UNIX", line.rstrip()
}}}
----
For a given file, check the first line and determine if it's Unix or Dos newline.
{{{
def getLineEndType(fpath):
ret = None
with open(f) as myfile:
# Grab the first line:
line = myfile.readline()
if line.find(r"\r\n") == -1:
ret = "DOS"
elif line.find(r"\n") == -1:
ret = "UNIX"
return ret
}}}
----
Convert a given file from one newline type to another. Uses the function {{{getLineEndType()}}} from above. This is a heavily modified version of the code I found [[here|http://www.java2s.com/Code/Python/Utility/ChangeLFlineendingstoCRLFUnixtoWindows.htm]]
{{{
import re
import os
def main(filename, mode, verbose=True):
"""
Convert the given file to either DOS ('\r\n') or UNIX ('\n') line endings.
If the line-endings are already the given type, do nothing.
Parameters:
filename : string : Full path to file.
mode : The line-ending to convert to. Either "DOS" or "UNIX".
"""
assert mode in ('DOS', 'UNIX'), "The argument passed to 'mode' must be either 'DOS' or 'UNIX'"
if not os.path.isfile(filename):
raise IOError("Missing file on disk: %s"%filename)
currentLineEnd = getLineEndType(filename)
if currentLineEnd == mode:
if verbose:
print "No change to file: Already %s"%mode
return
if not os.access(filename, os.W_OK): # is it writable?
raise Exception("The given file is read-only: %s"%filename)
data = open(filename, "rb").read()
if mode == "DOS":
# unix to dos:
newdata = re.sub("\r?\n", "\r\n", data)
elif mode == "UNIX":
# dos to unix:
newdata = re.sub("\r\n", "\n", data)
# This check is a bit redundant: We shouldn't have got this far based on
# the getLineEndType test above. But why not, eh?
if newdata != data:
if verbose:
print "Converted", filename, "to", mode
f = open(filename, "wb")
f.write(newdata)
f.close()
elif verbose:
print "No change needed: Already %s"%mode
}}}
Not that I run into this very often, BUT, it's nice to know :)
@@NOTE:@@ {{{sys._geframe()}}} is a {{{CPython}}} implementation detail: the leading underscore is telling you this is behind the scenes magic, and you shouldn't play with it, because it could change in future versions, or not be available in other Python implementations. Use at your own risk...
----
Presume you have some {{{moduleA.py}}}, and it imports {{{moduleB.py}}}. But in {{{moduleB.py}}}, you want to see some of the data in {{{moduleA.py}}}. How to do?
By using the {{{sys._getframe(1).f_locals}}} command (mouthfull!), you can peek into that enclosing scope:
Note that import happens *after* variable declaration...
{{{
# moduleA.py
foo = 23
sho = "asdf"
import moduleB
}}}
{{{
# moduleB.py
import sys
moduleA_stuff = sys._getframe(1).f_locals
print moduleA_stuff
}}}
When you then run {{{moduleA.py}}} at the prompt, you get this as the printed result (reformatted slightly to make easier to read), {{{f_locals}}} returns a dict:
{{{
{'__builtins__': <module '__builtin__' (built-in)>,
'__file__': 'C:\\Documents and Settings\\<userName>\\My Documents\\python\\moduleA.py',
'__name__': '__main__',
'foo': 23,
'__doc__': None,
'sho': 'asdf'}
}}}
From the docs on {{{sys._getframe}}}
http://docs.python.org/library/sys.html#sys._getframe
<<<
Return a frame object from the call stack. If optional integer depth is given, return the frame object that many calls below the top of the stack.
<<<
Frame Objects: ({{{f_locals}}})
http://docs.python.org/reference/datamodel.html#index-834
----
So my //guess// is, {{{sys._getframe(1).f_locals}}} is getting a frame object one {{{(1)}}} level up from the current location, which happens to be top most (global) scope of the enclosing module {{{moduleA.py}}}, and it's then getting the results of {{{f_locals}}}, which from the docs is: "...the dictionary used to look up local variables". We could have also used {{{f_globals}}} here and got the same results, since in this case locals and globals are the same thing.
I wanted to know if a program had a connection to the internet. Based on [[this thread|http://stackoverflow.com/questions/3764291/checking-network-connection]], here is a modified solution:
{{{
import socket
def canHazInternet():
try:
socket.gethostbyname("www.google.com")
return True
except:
return False
print canHazInternet()
# True
}}}
{{{
import P4
p4 = P4.P4()
p4.connect()
isConnected = p4.connected()
p4.disconnect()
}}}
https://www.perforce.com/perforce/doc.current/manuals/p4script/03_python.html#1120136
This works on Window.. but can provide incorrect results on Mac:
{{{
import platform
platform.architecture()
('64bit', '')
}}}
This seems hacky, but it works... at least on a Windows system:
{{{
import sys
print sys.version
split = sys.version.split()
bit = split[split.index('bit')-1]
print bit
}}}
{{{
2.6.1 (r26:67517, Dec 4 2008, 16:59:09) [MSC v.1500 64 bit (AMD64)]
64
}}}
This became a bigger deal once Window's 10 came out :S
Found this answer here:
http://stackoverflow.com/questions/34500369/open-cmd-with-admin-rights-windows-10/34500631
{{{
import ctypes, os
try:
is_admin = os.getuid() == 0
except AttributeError:
is_admin = ctypes.windll.shell32.IsUserAnAdmin() != 0
print is_admin
}}}
----
Also see:
* [[How can I run an executable with admin privileges in Windows?]]
If a file lives in Perforce, the {{{fstat}}} command will return a bunch of info on it. If it doesn't live in P4, it returns an empty list.
Via the Perforce Python API:
{{{
import P4
p4 = P4.P4()
# only raise excptions on errors, not warnings:
p4.exception_level = 1
p4.connect()
result = p4.run_fstat(pathToMyFile)
p4.disconnect()
if result:
print "Lives in P4!", pathToMyFile
else:
print "Not in P4!", pathToMyFile
}}}
Few different systems listed below:
----
Pulled info from [[this post|http://techarttiki.blogspot.com/2008/08/read-only-windows-files-with-python.html]], changed it a bit below:
http://docs.python.org/library/stat.html
http://docs.python.org/library/os.html#os.stat
{{{
import os
import stat
# define some magic values:
writable = 33206
readonly = 33060
myFile = r'c:/temp/mayFile.txt'
statInfo = os.stat(myFile)
fileState = statInfo.st_mode
if fileState == readonly:
print "File is read-only, made writeable."
os.chmod(myFile, stat.S_IWRITE)
elif fileState == writable:
print "File is writeable, make read-only."
os.chmod(myFile, stat.S_IREAD)
}}}
{{{os.stat}}} returns an object which has a bunch of attrs. One of them, {{{.st_mode}}}, contains some magic values that mean if the file is readable or writable. Checking against those values tells you what state its in, at which point you can use {{{os.chmod}}} passing in attrs from the {{{stat}}} //module// to update the state. Kind of wacky if you ask me ;)
----
Another query system:
http://docs.python.org/library/os.html#os.access
{{{
import os
os.access(file, os.F_OK) # does it exist?
os.access(file, os.R_OK) # is it readable?
os.access(file, os.W_OK) # is it writable?
os.access(file, os.X_OK) # is it executable?
}}}
----
Another way for making writable:
http://docs.python.org/library/os.html#os.chmod
{{{
import os
# Python 2
os.chmod("c:/temp/foo.txt", 0777)
# Python 3
os.chmod("c:/temp/foo.txt", 0o777)
}}}
We use junctioned paths, and it seems way to hard to figure out what the 'real' path is. Here's a clunky method I came up with:
{{{
import subprocess
import re
path = "c:/some/path/to/a/file/probably/junctioned/somehwere.txt"
splitPath = path.replace("\\", "/").split("/")
splitPath.pop()
junctions = []
for i in range(1,len(splitPath)):
repath = "\\".join(splitPath[:-i])
outIn = subprocess.Popen(["cmd", "/c", "dir", "/A:L"], cwd=repath,
stdout=subprocess.PIPE, shell=False).communicate()
for line in outIn[0].split("\r\n"):
if "<JUNCTION>" in line:
juncSplit = re.split('[\[\]]', line)
for js in juncSplit:
if js.count("\\") >=2:
# We need to 'clean' the start of the path, since the dir command
# can return stuff back like this: '/??/q:/mappedDrive/somePath'
# we want to record everything starting with p:
cleanPath = ""
foundDrive = False
for char in js:
if char in string.ascii_letters:
foundDrive = True
if not foundDrive:
continue
cleanPath += char
junctions.append([repath.replace("\\", "/"), cleanPath.replace("\\", "/")])
break
print junctions
[["c:/some/path", "q:/mappedDrive/somePath"]]
}}}
You can use {{{isinstance}}} on the type, vs {{{collections.Iterable}}}:
{{{
from collections import Iterable
types = ("string", ["a","list"], ("a", "tuple"), 1, 1.0, True)
}}}
{{{
for t in types:
print( t, type(t), "Is iterable?", isinstance(t, Iterable) )
}}}
{{{
string <type 'str'> Is iterable? True
['a', 'list'] <type 'list'> Is iterable? True
('a', 'tuple') <type 'tuple'> Is iterable? True
1 <type 'int'> Is iterable? False
1.0 <type 'float'> Is iterable? False
True <type 'bool'> Is iterable? False
}}}
However, this passes {{{string}}} as an iterable, //which it is//. Often times though, I only want to pass {{{list}}} or {{{tuple}}} as my sequence... this is the only short method I've found so far:
{{{
for t in types:
print (t, type(t), "Is list/tuple?", isinstance(t, (list,tuple)))
}}}
{{{
string <type 'str'> Is list/tuple? False
['a', 'list'] <type 'list'> Is list/tuple? True
('a', 'tuple') <type 'tuple'> Is list/tuple? True
1 <type 'int'> Is list/tuple? False
1.0 <type 'float'> Is list/tuple? False
True <type 'bool'> Is list/tuple? False
}}}
{{{
import inspect
def spam():
pass
print inspect.isfunction(spam)
}}}
{{{
True
}}}
Python as the concept of the 'current working directory'. You can query this via the {{{os}}} module:
{{{
import os
homeDir = os.getcwd()
# c:\Documents and Settings\<userName>\My Documents\python
}}}
You can also change this dir to be a user-defined value:
{{{
os.chdir("c:/temp")
print os.getcwd()
# 'c:\\temp'
}}}
[[chdir docs|http://docs.python.org/library/os.html#os.chdir]]
[[getcwd docs|http://docs.python.org/library/os.html#os.getcwd]]
{{{
import uuid
mac = hex(uuid.getnode())
print(mac)
0x70f1a123f094
}}}
Or this craziness, found [[HERE|https://www.geeksforgeeks.org/extracting-mac-address-using-python/]]:
{{{
mac = ':'.join(['{:02x}'.format((uuid.getnode() >> ele) & 0xff) for ele in range(0,8*6,8)][::-1])
print(mac)
70:f1:a1:23:f0:94
}}}
Which is the same value as if you did this on your Windows PC:
{{{
> ipconfig /all
...lots of stuff...
Ethernet adapter Ethernet:
Physical Address. . . . . . . . . : 70-F1-A1-23-F0-94
}}}
By getting and querying a 'frame object':
http://docs.python.org/library/inspect.html#inspect.currentframe
http://docs.python.org/library/inspect.html#types-and-members
{{{
import inspect
def getLine():
return inspect.currentframe().f_back.f_lineno
}}}
You can now do something like this anywhere in your code:
{{{
print "The current line is: %d"%getLine()
}}}
----
Note from the docs on {{{inspect.currentframe}}}
<<<
~CPython implementation detail: This function relies on Python stack frame support in the interpreter, which isn’t guaranteed to exist in all implementations of Python. If running in an implementation without Python stack frame support this function returns None.
<<<
{{{
import datetime
print datetime.date.today()
# 2008-05-19
print datetime.datetime.now()
# 2009-06-24 15:35:37.787000
}}}
You can compare dates:
{{{
import datetime
future = datetime.datetime(2020, 3, 24, 20, 10, 30)
now = datetime.datetime.now()
print now > future
}}}
http://docs.python.org/2/library/datetime.html
Using the [[Python API|http://www.perforce.com/perforce/doc.current/manuals/p4script/03_python.html#1116373]]
{{{
from P4 import P4
p4 = P4()
# Only raise exceptions, not warnings
p4.exception_level = 1
p4.connect()
data = p4.run_describe("1234567890")
p4.disconnect()
clFiles = data[0]['depotFile']
}}}
----
Also see:
*[[How can I sync to a Perforce changelist?]]
You can access the special {{{__module__}}} attribute on the given function object:
{{{
# myModule.py
def spam():
pass
def main():
print spam.__module__
}}}
This will print {{{myModule}}} when ran.
Docs on special module attrs [[here|http://docs.python.org/reference/datamodel.html#the-standard-type-hierarchy]], under the 'Callable types' section.
Access the {{{__name__}}} attribute of the given function:
{{{
def myfunc():
pass
print myfunc
print myfunc.__name__
}}}
{{{
<function myfunc at 0x0000000002D28F98>
myfunc
}}}
Kind-of practical example: You want to print both the function name called too, plus capture its return value for the user to see:
{{{
def myfuncA():
return "spam"
def myfuncB():
return "eggs"
for func in (myfuncA, myfuncB):
print "Function %s() returned"%func.__name__, func()
}}}
{{{
Function myfuncA() returned spam
Function myfuncB() returned eggs
}}}
http://docs.python.org/library/sys.html#sys.platform
{{{
import sys
print sys.platform
# win32
}}}
What's interesting, is that when I run this on my Windows Vista 64-bit box, with 64-bit Python installed, it still prints{{{win32}}}.
hmmm.....
In a module, this is trivial:
{{{
import sys
print sys.executable
print sys.prefix # install dir
}}}
On the PC:
{{{
C:\Python27\python.exe
C:\Python27
}}}
On the Mac:
{{{
/Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python
/Library/Frameworks/Python.framework/Versions/2.7
}}}
On Linux (my Raspberry Pi Rasberian distro):
{{{
/usr/bin/python
/usr
}}}
----
Also, on the Mac, from a shell, you can execute:
{{{
$ which python
/Library/Frameworks/Python.framework/Versions/2.7/bin/python
}}}
Or Linux:
{{{
$ which python
/usr/bin/python
}}}
It's interesting to note that the browse to that dir, and execute Python, and then print {{{sys.executable}}}, it will actually return the longer path shown above. I'm guessing the path returned by {{{which}}} is actually some sort of simlink.
The [[sys.getsizeof()|http://docs.python.org/dev/library/sys.html#sys.getsizeof]] function will return the size of the given object, in bytes.
{{{
import sys
print sys.getsizeof('a')
# 41
}}}
So apparently, the {{{string}}} object takes up 41 bytes.
{{{os.environ}}} returns a [[Dictionary|DICTIONARY]]
Note: Both methods query a combination of USER and SYSTEM env vars. If you want a solution that only queries the system, check out this solution:
http://code.activestate.com/recipes/473800-getting-system-environment-variable-under-windows/
{{{
import os
var = os.getenv("PATH")
# or
var = os.environ["PATH"]
}}}
----
Also see:
*[[How can I get a list of Environment Variables?]]
*[[How can I set an environment variable?]]
{{{vars()}}} - [[Python Docs|http://docs.python.org/dev/library/functions.html#vars]]
{{{vars()}}} can be used in two ways: You can pass an object into it, or not.
*If you //don't// pass in an object reference, it will return back a dictionary of the //current local [[scope's|Python variable scope]]// variable names.
*If you pass in an object reference, it will return a dictionary corresponding to that object's [[attribute]] [[namespace]] (also known as it's [[__dict__|Understanding __dict__]], or 'symbol table')
From the docs:
<<<
Without arguments, return a dictionary corresponding to the current local symbol table. With a module, class or class instance object as argument (or anything else that has a {{{__dict__}}} attribute), returns a dictionary corresponding to the object’s symbol table. The returned dictionary should not be modified: the effects on the corresponding symbol table are undefined.
<<<
The below example will return back the {{{__dict__}}} of the current scope:
{{{
D = vars()
for key in D:
print key, str(D[key])
}}}
{{{
import sys
for key in sorted(sys.modules):
print key,sys.modules[key ]
}}}
The key is the module name (like myPackage.myModule), and the value is the module object itself.
{{{
type(["asdf", "fdsa"])
# Result: <type 'list'> #
type(3)
# Result: <type 'int'> #
import os
type(os)
# Result: <type 'module'> #
type(open)
# Result: <type 'builtin_function_or_method'> #
type(type)
# Result: <type 'type'> #
}}}
Some options...
----
1. You can use {{{inspect.getfile}}} or {{{inspect.getabsfile}}} to return the path to the module:
{{{
import foo
import inspect
print inspect.getfile(foo)
print inspect.getabsfile(foo)
# c:\pylib\foo.py
# c:\pylib\foo.py
}}}
----
2. Calling {{{help(moduleName)}}} will print out lots of info on the module, including where it's saved.
----
3. Calling {{{reload(moduleName)}}} will also tell you where it was reloaded from
----
4. Some modules have the full path in their special {{{__file__}}} attr, while others only have the filename. Still others have no {{{__file__}}} attr at all. You can use the {{{inspect}}} function above irregardless. But //sometimes// you can use this method too:
{{{
# inspect happens to have a valid .__file__ attr... not all modules do
import inspect
print inspect.__file__
# c:\Python25\lib\inspect.pyc
}}}
OR, inside your module, you can just do this:
{{{
# myModule.py
print os.path.abspath(__file__)
}}}
Would print when executed:
{{{
c:\pyStuff\myModule.py
}}}
----
Also see:
*[[How can a module reference where itself has been saved?]]
*[[Getting module save locations]]
*[[How can a module query relative directories to where it has been saved?]]
If you are iterating over a long {{{for loop}}}, or in a {{{while loop}}} running forever, how can you cancel out?
An easy solution is to wrap the loop in a try\except checking for a {{{KeyboardInterrupt}}}, which is spawned via the user pressing {{{ctrl+c}}} in the active Python shell. If it catches that exception, you can exit out of the func:
{{{
# myAwesomeModule.py
def main():
try:
while True:
print "running!"
except KeyboardInterrupt:
print "Cancled via ctrl+c"
return
if __name__ == "__main__":
main()
}}}
I heard about a scientist that figured out that if you randomize the letters of a word, if the first and last letters remain the same you can still read the word. Took a shot at doing it in Python:
{{{
import random
def shuffler(sentence):
words = sentence.split(' ')
updated = []
for word in words:
if len(word) >= 4:
mid = list(word[1:-1])
random.shuffle(mid)
newWord = '%s%s%s'%(word[0], ''.join(mid), word[-1])
updated.append(newWord)
else:
updated.append(word)
result = ' '.join(updated)
return result
print shuffler("You can randomize all the letters in the middle of a word and still be able to read them.")
}}}
{{{
You can rmzaodine all the lteters in the mddlie of a wrod and sitll be albe to read tehm.
}}}
And strip off the newline characters in the process?
Using a [[context manager|with statement]] (and list comprehension), Python 2.6+:
{{{
with open("myFile.txt", 'r') as f:
lines = [item.rstrip() for item in f]
print lines
}}}
If you just want the lines and not make any changes:
{{{
with open("myFile.txt", 'r') as f:
lines = list(f)
}}}
----
{{{
f = open('myfile.txt', 'r').readlines()
filelist = []
for item in f:
filelist += [item.rstrip()]
f.close()
}}}
The above works, but it loads the whole file into memory, then duplicates it in memory.
----
If you just want to iterate over each line in the file, this is much cleaner, and uses the file objects iterator method:
{{{
for line in open('myfile.txt'):
print line.rstrip()
# foo a
# foo b
# etc...
}}}
----
Here's yet another approach using iterators:
{{{
f = open('myfile.txt')
print f.next().rstrip()
# foo a
print f.next().rstrip()
# foo b
f.close()
}}}
If you reach the end of a file using this example, the {{{.next()}}} method will raise {{{StopIteration}}}
----
Another way, using a list comprehension:
{{{
lines = [line.rstrip() for line in open('myfile.txt', 'r')]
print lines
# ['foo a', 'foo b', etc...]
}}}
----
Per this:
https://stackoverflow.com/questions/397125/reading-the-target-of-a-lnk-file-in-python
Not pure Python, since you need win32com, but it works:
{{{
import win32com.client
pth = r"C:\path\to\some\file.txt.lnk"
shell = win32com.client.Dispatch("WScript.Shell")
shortcut = shell.CreateShortCut(pth)
print(shortcut.Targetpath)
# C:\path\to\the\real\file.txt
}}}
In this simple example, a file is opened, and each line is iterate over until a condition is met. This has the advantage of not needing to load the whole file in memory first before iteration.
{{{
fpath = "C:/path/to/my/file.txt"
with open(fpath) as inf:
line = inf.next().strip()
while not line.startswith("Some condition string"):
print line
line = inf.next().strip()
}}}
----
Docs:
*[[open|http://docs.python.org/2/library/functions.html#open]] function
*[[file|http://docs.python.org/2/library/stdtypes.html#bltin-file-objects]] objects
{{{
import os
import re
# path we should start searching:
startDir = r"c:\temp" # print startDir
# search parameter for filename we're looking for:
searchFile = ".py"
# when searching in the file on each line, string to look for:
searchString = "foo"
for dirpath, dirnames, filenames in os.walk(startDir):
print "Starting Search:\n"
for fil in [f for f in filenames if f.endswith(searchFile)]:
result = []
fh = open(dirpath + "\\" + fil)
for i,line in enumerate(fh):
if re.search(searchString, line):
result.append("\t"+ str(i) + ": " +line.strip())
if len(result):
print (dirpath + "\\" + fil )
for r in result:
print r
fh.close()
print "\nEnding Search\n"
# Starting Search:
#
# c:\temp\spam.py
# 84: foo = 24
# 211: goo = foo
#
# Ending Search
}}}
----
If the files are very large, you can use the {{{mmap.mmap}}} object instead. This seems to help performance:
Snippet:
{{{
for fpath in files:
with open(fpath) as f:
s = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
if s.find(searchString) != -1:
found.append(fpath)
}}}
----
Also see:
*[[How can I get a recursive list of directories?]]
*[[How can I search for files in directories faster than os.walk?]]
{{{
# The official Perforce Python API:
from P4 import P4
p4 = P4()
p4.connect()
rootDirs = ["//myDepot/someRoot"]
for rd in rootDirs:
if not rd.endswith("/"):
rd += "/"
subdirs = p4.run("dirs", "-C", '%s*'%rd)
if not subdirs:
continue
# subdirs is a list of dicts:
for dic in subdirs:
# the dir name is the single value in the dict:
sd = dic.values()[0]
rootDirs.append(sd)
p4.disconnect()
for d in rootDirs:
print d
}}}
It should be noted that if you want to get a recursive list of //files//, this can be easily done via the Perforce [[files|http://www.perforce.com/perforce/doc.current/manuals/cmdref/files.html]] command.
----
P4 Docs:
*[[dirs|http://www.perforce.com/perforce/r12.1/manuals/cmdref/dirs.html]]
----
Also see:
*[[How can I recursively search for files in Perforce?]]
{{{
# The official Perforce Python API:
from P4 import P4
p4 = P4()
p4.connect()
rootDir = "//myDepot/someRoot"
if not rootDir.endswith("/"):
rootDir += "/"
# Our list of files:
files = p4.run("files", "%s....XANIM_EXPORT"%rootDir)
# Convert them to something readable, lots of extra data in there:
fileList = []
for f in files:
# Filter out deleted files:
if 'delete' in f['action']:
continue
if 'depotFile' in f.keys():
fileList.append(f['depotFile'])
clientFiles = []
# Convert from depot path to client path:
for f in fileList:
data = p4.run('fstat', f)
if not data:
continue
if 'clientFile' in data[0].keys():
cf = data[0]['clientFile'].replace("\\", "/")
clientFiles.append(cf)
for cf in clientFiles:
print cf
p4.disconnect()
}}}
----
P4 docs:
*[[files|http://www.perforce.com/perforce/doc.current/manuals/cmdref/files.html]]
*[[fstat|http://www.perforce.com/perforce/doc.current/manuals/cmdref/fstat.html]]
----
Also see:
*[[How can I recursively search for directories in Perforce?]]
You can use the {{{round}}} built-in function:
{{{
num = 1.2345
print round(num, 2)
# 1.23
}}}
----
If you simply want to print a shorter number, but not actually modify the value itself, please see:
[[Format floating point precision for printing]]
The magical {{{reload}}} built-in function, but this only works in Python 2.x:
{{{
reload(myModule)
}}}
In Python 3.x, they yanked it. How to do? I fake it this way for code that may need to run in either version:
{{{
try:
reload
except NameError:
from importlib import reload
}}}
{{{
seq = ["a", "b", "c", "a", "b", "c"]
seq = list(set(seq))
print seq
# ['a', 'c', 'b']
}}}
By using {{{set}}}s (which can't hold duplicate values), you can prune out the dupes.
{{{
# Rename all text files in a dir
import os
from glob import glob
path = "c:/path/to/the/files/"
files = glob("%s*.txt"%path)
for f in files:
newName = f.replace("oldString", "newString")
os.rename(f, newName)
}}}
This is a pretty simply example: It will iterate over each line in a file, and if it finds 'oldText' in that line, it will replace it with 'newText'. It does this by reading the file into a list, modifying the list, then writing the list back on top of the file.
{{{
def repath(fname, oldText, newText):
with open(fname, 'r') as f:
lines = [item for item in f]
newLines = []
for line in lines:
if oldText in line:
line = line.replace(oldText, newText)
newLines.append(line)
with open(fname, 'w') as f:
f.writelines(newLines)
}}}
----
Alternately, if you want to replace the text //in place// in the file, you can use this solution that makes use of the {{{fileinput}}} module. As you can see, it redirects {{{sys.stdout}}} to write directly into the open file.
*http://docs.python.org/2/library/fileinput
*http://stackoverflow.com/questions/1582750/edit-text-file-using-python/2363893#2363893
{{{
import sys
import fileinput
myfile = "c:/temp/myfile.txt"
for i, line in enumerate(fileinput.input(myfile, inplace=1)):
sys.stdout.write(line.replace('line', 'spam'))
}}}
It will go through each line of the file replacing any 'line' text with 'spam'.
You can comment on this over on my [[main blog|http://www.akeric.com/blog/?p=312]].
I process a lot of paths. Some of these paths are entered by hand, by a human. Other paths are machine generated by some tool. Sometimes the tool will respect the case entered originally, other times it makes everything lowercase. Based on these combinations, you could be dealing with two paths that are the exact same (location on disk), but some have upper-case characters defining part of their name, and others, lower-case text. If you need to process these paths, and change them from one relative path to another, these case inconsistencies can become a real pain. Below is //one// solution around the issue. I'd be interested to see others :)
Using {{{re.findall}}}, we can search in a string. But what really helps is {{{re.IGNORECASE}}}. This gives us a matching string based on the //case of the source string//, which we can then use to replace with later using the {{{.replace()}}} string method:
{{{
import re
srcPath ="c:/my/path/wIth/mIxeD/case"
match = "/with/mixed/"
replace = "/normal/"
resultPath = ""
try:
sourceCaseMatch = re.findall(match, srcPath, re.IGNORECASE)[0]
resultPath = srcPath.replace(sourceCaseMatch, replace)
except:
pass
print "Result: '" + resultPath + "'"
# Result: 'c:/my/path/normal/case'
}}}
Figured this would be a built-in method, but it is not.
From [[here|https://stackoverflow.com/questions/931092/reverse-a-string-in-python]]
{{{
>>> 'hello world'[::-1]
'dlrow olleh'
}}}
For Python 2.7:
{{{
import ctypes
myExePath = "c:/some/path/to/an/app.exe"
ctypes.windll.shell32.ShellExecuteW(None, u"runas", unicode(os.path.normpath(myExePath)), None, None, 1)
}}}
https://docs.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-shellexecutew
----
Also see:
*[[How can I query if Python is ran with admin privilages in Windows?]]
<<<
''Update'': I lied below. It's just as slow :( After the first time you search it appears that the data is cached, which causes future searches to be faster. After restarting my machine, the below method was just as slow. But I'll leave the subject around //as a warning to others.// ;)
<<<
As explained in other subjects, you can use Python's {{{os.walk}}} to recursively walk the directory tree. However, I've found this to be really slow at times depending on what you're looking for, and how bit the tree is that's being searched.
A quicker way (for myself at least) is rather than calling on Python to search the tree, call to the OS directly. In my case I'm using Windows7, and a combination of the dos {{{DIR}}} and {{{FINDSTR}}} commands do the job.
In the below example, I set a starting search path to be {{{C:\my\Path}}}. Then I query for all subdirs named {{{\someSubDir}}} and loook for all files that end with the string {{{_postfix.py}}}. I execute the command, and capture the return via {{{subprocess.Popen}}}, and clean up the results via a [[list comprehension]]:
{{{
import subprocess
dosCmd = r'DIR C:\my\Path e /s /b |FINDSTR /R \\someSubDir\\.*_postfix\.py$'
result = subprocess.Popen(dosCmd, shell=True, stdout=subprocess.PIPE).communicate()
data = [f.strip() for f in result[0].split("\r\n") if f != ""]
for d in data :
print d
}}}
I've found that in my case a search via {{{os.walk}}} which easily could have taken 30-45 seconds is reduced to less than 1 second.
The below function simply takes in a string (presumably some Python command), and will open a web browser, using Google to search for the command in {{{docs.python.org}}}
{{{
import urllib
import webbrowser
def searchPyhonViaGoogle(txt):
"""
Search docs.python.org via google for the provided
command, and launch a browser
txt : (str) The Python command to search for
"""
url = urllib.urlencode((('q', txt + ' site:docs.python.org'), ('ie', 'utf-8')))
url = "http://www.google.com/search?" + url
webbrowser.open_new(url)
}}}
http://docs.python.org/library/os.path.html#os.path.isdir
http://docs.python.org/library/os.html#os.mkdir
http://docs.python.org/library/os.html#os.makedirs
http://docs.python.org/library/os.path.html#os.path.lexists
The below code works if the parent dir (in this case, {{{/temp}}}) already exists:
{{{
import os
if not os.path.isdir("c:/temp/myPath"):
os.mkdir("c:/temp/myPath")
}}}
You can also use for the test:
{{{
os.path.lexists("c:/myPath")
}}}
{{{os.mkdir}}} only makes leaf directories. If you need to build a series of intermediate directories at the same time (in the below example, {{{/temp}}} already exists, but {{{/spam}}} doesn't), you need to use:
{{{
import os
path = 'c:/temp/spam/eggs'
if not os.path.isdir(path):
os.makedirs(path)
}}}
Which will error if the leaf dir already exists, that's why we need to check first.
A variety of ways, see below.
''Important things'':
*Adding a slash at the END of a path seems to make it not be recognized, so avoid that.
*Python likes it's paths to have //backslashes// : {{{\}}} . Forwardslahes don't work so well. Flee from them.
----
''Updating Solutions'':
You can do it on the fly in your modules this way (but see notes on ''trickery'' at the bottom):
{{{
import sys
sys.path += ["c:\\someNewPath"]
# or
sys.path.append("c:\\someNewPath")
}}}
I've also seen problems when using double-backslashes and some letter combo's: Python turns them into special characters, and mangles the path. This next example is what I actually use, utilizing a 'raw' string, and //forwardslashes//:
{{{
import sys
import os
sys.path.append(os.path.normpath(r"c:/someNewPath"))
}}}
----
You can set\modify the 'PYTHONPATH' environment variable. These are added to the head of {{{sys.path}}}:
{{{
PYTHONPATH = c:\someNewPath;
}}}
----
Create {{{.pth}}} files, each which contains a //single path//. Store them in your python install dir, like:
{{{
c:\pythonXX\myCustompath.pth
}}}
Also see the [[site|http://docs.python.org/library/site.html]] module
----
Modify the site.py file, updating {{{sys.path}}} in that file. The drawback is if you ever reinstall Python, this will be overwritten.
{{{
c:\PythonXX\Lib\site.py
}}}
----
Some ''trickery'':
If you are authoring code in a IDE that allows for 'Evaluate Selection' (you can highlight blocks of text, and execute them withought having to make them their own module), when executing a selection of lines that includes pathing updates, it appears that the path updates don't 'stick' past the execution evaluation. Immediately after execution, if you query {{{sys.path}}}, the update //won't// be there. If you execute a code-block that includes pathing updates, and importing of modules from said update all at once, it //will// work, even though after the fact the path //won't// have your update. Executing the code line-by-line won't work either (since each line-block will forget any pathing info defined). //However//, if you embed this update into a module\function, and execute said function (the //normal// way of doing things, the updates will stick. Odd.
----
Also see
*[[Packages]]
*[[How can I append to Python's site-packages dir?]]
! In the Windows Registry:
You can wrapper the Windows system call:
{{{
> setx VAR_NAME "var value" /M
}}}
Like so:
{{{
import subprocess
result = subprocess.Popen(["setx", "TEMP_VAR", "var value", "/M"], stdout=subprocess.PIPE).communicate()
print result
# ('\r\nSUCCESS: Specified value was saved.\r\n', None)
}}}
The {{{/M}}} saves it in the system-level registry. If you omit it, it will save in the current 'user' registry.
@@Note@@ : {{{/M}}} may only work if the current shell or Python console was launched with admin permissions.
! In the active process:
If you can query an environment variable via [[os.getenv|http://docs.python.org/2/library/os.html#os.getenv]] like so:
{{{
import os
myvar = os.getenv("MYVAR")
}}}
You'd //think// you'd be able to able to set one like the same way, via [[os.putenv|http://docs.python.org/2/library/os.html#os.putenv]]:
{{{
os.putenv("MYVAR", "my var value")
}}}
On Windows however, {{{putenv}}} doesn't seem to do anything.... :-S
To actually update the var, you need to update via [[os.environ|http://docs.python.org/2/library/os.html#os.environ]]
{{{
os.environ["MYVAR"] = "my var value"
}}}
----
Also see:
*[[How can I get a list of Environment Variables?]]
From this link:
http://stackoverflow.com/questions/7387276/set-window-name-in-python
On Windows:
{{{
from os import system
system("title %s"%theTitle)
}}}
Via [[pywin32]]:
{{{
win32console.SetConsoleTitle("The Title")
}}}
Via the commandline:
{{{
> python myModule.py -t The Title
}}}
I've encountered weird bugs in certain applications (like Unreal), where if you have a ~PySide window open and you close the parent application, the application will actually crash after it closes. This seems harmless, but is annoying & scares my users.
Some applications allow for callbacks that can execute python code when they close: If so, you can pass it the below {{{onPythonShutdown}}} function to execute, which will shut down ~PySide first, skirting the bug.
{{{
try:
from PySide.QtGui import QApplication
except ImportError:
from PySide2.QtWidgets import QApplication
def onPythonShutdown():
QApplication.instance().quit()
}}}
Docs for:
* ~PySide: [[QApplication|https://srinikom.github.io/pyside-docs/PySide/QtGui/QApplication.html]]
* ~PySide2: [[QApplication|https://doc.qt.io/qtforpython/PySide2/QtWidgets/QApplication.html]]
Easy enough to sort a dictionary by key, but how do you sort it by value?
{{{
dic = {"a":1.0, "c":3.0, "b":2.0, "d":1.0}
}}}
{{{
# Example #1
from operator import itemgetter
dList = sorted(dic.items(), key=itemgetter(1))
print dList
}}}
{{{
# Example #2
dList = dic.items()
dList.sort(key=lambda x: x[1])
print dList
}}}
They both print:
{{{
[('a', 1.0), ('d', 1.0), ('b', 2.0), ('c', 3.0)]
}}}
As you can tell from example #1, it's {{{sorted}}} function using the {{{operator.itemgetter}}} function that does the magic. Docs:
http://docs.python.org/library/functions.html#sorted
http://docs.python.org/library/operator.html#operator.itemgetter
For example #2, it's the method {{{list.sort}}} and {{{lambda}}}. Docs:
http://docs.python.org/tutorial/datastructures.html#more-on-lists
http://docs.python.org/reference/expressions.html#lambda
----
Example #3:
The trick described below is to use a custom compare function which does a value comparison based on the passed in tuples, that is passed to the {{{sorted}}} function:
{{{
def srtCmp(x, y):
"""
x & y : (key, value) : Both x & y are expected to
be tuples of key:value pairs.
"""
keyX, valX = x
keyY, valY = y
if valX < valY:
return -1
elif valX == valY:
return 0
elif valX > valY:
return 1
# Make a dict with values we want to sort by:
d = {"A":1.0, "C":5.2, "Q":0.5}
# Return a list of tuples of the dict items,
# sorted by their value, rather than key:
# The items() method returns a list of
# tuple (key,value) pairs.
goodSort = sorted(d.items(), cmp=srtCmp)
# Returns the dict items in order or their sorted
# *keys* (not what we want).
badSort = [(key, d[key]) for key in sorted(d)]
print badSort
print goodSort
[('A', 1.0), ('C', 5.2), ('Q', 0.5)] #bad, by key
[('Q', 0.5), ('A', 1.0), ('C', 5.2)] #good, by value
}}}
You can create a custom sorter function that compares the modification date of the passed in list of files:
{{{
import os
import glob
def sortByDate(a,b):
"""
Custom sort function designed to sort a list of files based on their
modification date.
"""
aTime = os.path.getmtime(a)
bTime = os.path.getmtime(b)
if aTime < bTime:
return -1
elif aTime == bTime:
return 0
elif aTime > bTime:
return 1
files = glob.glob("c:/temp/*.txt")
dateSortedFiles = sorted(files, cmp=sortByDate)
}}}
I recently had a list of axis vector names (see example below) that had both positive and negative names. When I'd sort the list, it would place the negative names first, since the minus character sorts before the alpha-numeric ones. The {{{sorted}}} function, or the list method {{{sorted}}} both accept a {{{cmp}}} argument that you can use to do your own sort rules. In my case, I wanted to make sure that the minus '-' characters got sorted after alpha-numeric ones.
http://docs.python.org/library/functions.html#sorted
http://docs.python.org/tutorial/datastructures.html#more-on-lists
http://docs.python.org/library/stdtypes.html#mutable-sequence-types
<<<
"{{{cmp}}} specifies a custom comparison function of two arguments (list items) which should return a negative, zero or positive number depending on whether the first argument is considered smaller than, equal to, or larger than the second argument"
<<<
----
As you can see, just sorting it doesn't do what I want:
{{{
print sorted(['x', 'y', 'z', '-x', '-y', '-z'])
# ['-x', '-y', '-z', 'x', 'y', 'z']
}}}
So, we make a sort rule:
{{{
# My cmp tester:
def negTest(x,y):
if '-' in x and '-' not in y:
return 0
else:
return 1
}}}
Using the list {{{sort}}} method, which changes the list in-place:
https://docs.python.org/3/library/functools.html#functools.cmp_to_key
{{{
# Python 3:
from functools import cmp_to_key
s.sort(key=cmp_to_key(negTest))
}}}
{{{
# Python 2
s.sort(cmp=negTest)
}}}
{{{
print s
# ['x', 'y', 'z', '-x', '-y', '-z']
}}}
Or using the {{{sorted}}} function, which creates a new list:
{{{
# Python 2
newS = sorted(s, cmp=negTest)
}}}
{{{
# Python 3
from functools import cmp_to_key
newS = sorted(s, key=cmp_to_key(negTest)
}}}
{{{
print newS
# ['x', 'y', 'z', '-x', '-y', '-z']
}}}
You can also use a {{{lambda}}} for the {{{cmp}}} arg, but my brain wasn't working well enough to make this happen.
{{{
from functools import cmp_to_key
def sortMultiDecimal(val1, val2):
if val1 == val2:
return 0
val1split = [int(val) for val in val1.split(".")]
val2split = [int(val) for val in val2.split(".")]
maxDecimal = max([len(val1split), len(val2split)])
for i in range(maxDecimal):
try:
val1split[i]
except IndexError:
return -1
try:
val2split[i]
except IndexError:
return 1
if val1split[i] > val2split[i]:
return 1
elif val1split[i] < val2split[i]:
return -1
vals = ["19.5.49900", "18.5.499", "17.5.49912341234", "1", "100.0"]
print(sorted(vals, key=cmp_to_key(sortMultiDecimal)))
['1', '17.5.49912341234', '18.5.499', '19.5.49900', '100.0']
}}}
I often encountered lists of names with numeric values on the end that have no zero padding. Meaning for example, a list of node names like so:
{{{['a1', 'a9', 'a10', 'a99', 'a100']}}}
Sorting this list with the default Python sort function will return it in an incorrect order though, since there is no zero padding in front of the numbers:
{{{
print sorted(['a1', 'a9', 'a10', 'a99', 'a100'])
['a1', 'a10', 'a100', 'a9', 'a99']
}}}
Python's {{{sorted}}} function takes a special '[[comparison function|http://docs.python.org/library/functions.html#sorted]]' argument that you can use to sort by your own rules.
----
New solution:
{{{
def endExtSrt(x,y):
"""
Used to sort non-padded names in the correct order.
"""
xNums = re.findall('[0-9]+$', x)
yNums = re.findall('[0-9]+$', y)
xNoNum = None
yNoNum = None
if xNums:
xNoNum = x[:-len(xNums[0])]
if yNums:
yNoNum = y[:-len(yNums[0])]
# Do the names match without numbers?
nameMatch = xNoNum == yNoNum
# If we find a number on both items, and their names match without the number:
if xNums and yNums and nameMatch :
numX = int(xNums[0])
numY = int(yNums[0])
if numX < numY:
return -1
if numX == numY:
return 0
if numX > numY:
return 1
# Otherwise, do normal sort:
else:
return cmp(x,y)
}}}
{{{
data = ['bob1', 'bob10', 'bob03', 'bob2', 'bob11', 'bob', 'joe', 'frank', 'apple']
print sorted(data)
# Python 2
print sorted(data, cmp=endExtSrt)
# Python 3:
from functools import cmp_to_key
print(sorted(data, key=cmp_to_key(endExtSrt)))
}}}
{{{
['apple', 'bob', 'bob03', 'bob1', 'bob10', 'bob11', 'bob2', 'frank', 'joe'] # incorrect order
['apple', 'bob', 'bob1', 'bob2', 'bob03', 'bob10', 'bob11', 'frank', 'joe'] # correct order
}}}
----
Older solution:
Below I create one of these functions, extract the numeric values from the end of each item, pad them with zero's (I figured a 32 values should be big enough for most of my needs), then compare the results:
{{{
import re
def sortTest(x, y):
try:
xNum = re.findall('[0-9]+$', x)[0]
xStr = x.rstrip(xNum)
except IndexError:
xNum = '0'
xStr = x
try:
yNum = re.findall('[0-9]+$', y)[0]
yStr = y.rstrip(yNum)
except IndexError:
yNum = '0'
yStr = y
# Rebuild our items with padded numeric values
xA = '%s%s'%(xStr, xNum.zfill(32))
yA = '%s%s'%(yStr, yNum.zfill(32))
if xA < yA:
return -1
elif xA == yA:
return 0
elif xA > yA:
return 1
data = ['a1', 'a2', 'a11', 'a113', 'a13', 'a21', 'a03', 'a30', 'a07']
print sorted(data)
# Python 2
print sorted(data, cmp=sortTest)
# Python 3:
from functools import cmp_to_key
print(sorted(data, key=cmp_to_key(sortTest)))
}}}
Prints:
{{{
['a03', 'a07', 'a1', 'a11', 'a113', 'a13', 'a2', 'a21', 'a30'] # incorrect order
['a1', 'a2', 'a03', 'a07', 'a11', 'a13', 'a21', 'a30', 'a113'] # correct order with custom sorter
}}}
From : https://stackoverflow.com/questions/43893126/how-to-split-camelcase-into-a-list-python
{{{
import re
word = "camelCaseWord"
print re.sub('([a-z])([A-Z])', r'\1 \2', word).split()
# ['camel', 'Case', 'Word']
}}}
{{{
pather = r"c:\temp\foo.txt"
print os.path.splitext(pather)
# ('c:\\temp\\foo', '.txt')
print os.path.splitext(pather)[0]
# c:\temp\foo
}}}
Given a list of items, I want to generate a list of sublists each with the same number of items:
{{{
stuff = [1,2,3,4,5,6,7,8,9]
step = 3
split = [stuff[i:i+step] for i in range(0, len(stuff), step)]
print split
# [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
}}}
{{{
spam = """one
two
three"""
items = spam.splitlines()
print items
# ['one', 'two', 'three']
}}}
Pythons built in string method {{{split()}}} ({{{"string".split("chars")}}}) works good for splitting a string based on a given sequence of characters. For example:
{{{
print "split|me:please".split("|")
# ['split', 'me:please']
}}}
But what if you wanted to split that line by both the pipe ({{{|}}}) and the colon ({{{:}}})? This would fail:
{{{
print "split|me:please".split("|:")
# ['split|me:please']
}}}
It fails because Python can't find an exact match of the string '{{{|:}}}'.
Here are several solutions using {{{re}}} that works nicely: (I found this info [[here|http://bytes.com/topic/python/answers/716054-s-split-multiple-separators]])
{{{
import re
word = "split|me:please"
reComp = re.compile('[|:]')
print reComp.split(word)
print re.split('[|:]', word)
print re.split('[|:]+', word)
print re.findall('[^|:]+', word)
}}}
All instances print:
{{{
['split', 'me', 'please']
}}}
----
Older function I wrote that works around the issue, kept for prosperity:
{{{
def charSplit(string, chars):
"""
string : The string in question to split
chars : list : list of strings to chop string up by
"""
splitted = [string]
for c in chars:
newSplit = []
for s in splitted:
chopped = s.split(c)
try:
chopped.remove("")
except ValueError:
pass
newSplit = newSplit + chopped
splitted = newSplit
return splitted
}}}
{{{
name = "namespace:one|namespace:two|namespace:three"
splitted = charSplit(name, list(":|"))
print splitted
}}}
{{{
['namespace', 'one', 'namespace', 'two', 'namespace', 'three']
}}}
By letting you pass in a list, you can still try to separate by multiple-character strings:
{{{
charSplit(name, ["|", "<>", "@@"])
}}}
Presuming you want to format names for proper windows directory or file names, what's a way to do it? I'm SURE there is a more elegant, Pythonic way to do this. Hey, I'm still learning! :) But this definitely works!
{{{
import string
def convertLegalName(txt):
result = ""
good = list(string.letters + string.digits + "_")
letters = list(txt)
for letter in letters:
if letter not in good:
result = result + "_"
else:
result = result + letter
return result
txt = "This line, has many (bad) characters that shouldn't be used at all!"
print convertLegalName(txt)
# This_line__has_many__bad__characters_that_shouldn_t_be_used_at_all_
}}}
I thought I'd try doing something similar with a [[list comprehension]]. This does the same as above, removes bad chars, but //doesn't// replace then with an underscore '_'. And it's much more 'Pythonic' I think ;)
{{{
def convertLegalName(txt, good):
done = ''.join([char for char in list(txt) if char in list(good)])
return done
# Usage:
import string
# this has some questionable characters in it...
txt = '<COLLADA version="0.4">'
good = string.printable
convert = convertLegalName(txt, good)
print convert
# <COLLADA version="0.4">
}}}
Also check out {{{string.printable}}} for every legal printable char (a combination of .letters, .digits, .punctuation, including 'space'), and {{{string.punctuation}}} for a list of, well, punctuation symbols.
I don't know if there is a better way (maybe with sets?), but I came up with this method using List Comprehensions:
{{{
listA = ["a","b"]
listB = ["b", "c"]
listC = [item for item in listB if item not in listA]
print listC
# ['c']
}}}
For example: {{{imp}}} is deprecated in Python 3+, but still works. How you can stop those warnings from happening during import (probably a bad idea to suppress, but none the less):
{{{
import warnings
with warnings.catch_warnings():
warnings.filterwarnings("ignore",category=DeprecationWarning)
import imp
}}}
{{{
# convert to forwardslash paths from backslash:
path = r"s:\tab\tab"
path = os.path.normpath(path).replace("\\", "/")
print path
# "s:/tab/tab"
}}}
{{{
# convert to backslashes from forwardslashes (on Windows):
path = "s:/tab/tab"
path = os.path.normpath(path)
print path
# "s:\tab\tab"
}}}
Came up with two different ways, one via the API, and one via the system. The API is nice, but I can't find any way to extract the results. Could just be my ignorance. Calling to P4 at the system level makes it easy to get the results:
{{{
# Via the P4 API:
import P4
changelist = 1234
p4 = P4.P4()
p4.connect()
# Only raise exceptions, not warnings
p4.exception_level = 1
print "Starting P4 sync for changelist %s"%changelist
p4.run_sync('@=%s'%changelist)
p4.disconnect()
}}}
{{{
# Via calls to the system:
import subprocess
changelist = 1234
print "Starting P4 sync for changelist %s"%changelist
result = subprocess.Popen(['p4', 'sync', '@=%s'%changelist],
stdout=subprocess.PIPE).communicate()
foo = [f.strip() for f in result[0].split("\r\n") if f != ""]
if len(foo):
for f in foo:
print "\t", f
else:
print "\tEverything is up to date."
print "Finished P4 changelist sync, see results above:"
}}}
http://www.perforce.com/perforce/doc.current/manuals/p4script/03_python.html#1116373
----
Also see:
*[[How can I sync to a Perforce changelist?]]
To find which version is running:
{{{
$ which python
/Library/Frameworks/Python.framework/Versions/2.7/bin/python
}}}
----
Info from [[this doc|http://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man1/python.1.html]]
To set the 'default python':
{{{
$ defaults write com.apple.versioner.python Version 2.7
}}}
To set a system-wide default, replace `{{{com.apple.versioner.python}}}' with `{{{/Library/Preferences/com.apple.versioner.python}}}' ({{{sudo}}} admin privileges will be required).
These can also be set by env vars:
{{{
$ export VERSIONER_PYTHON_VERSION=2.7 # Bourne-like shells
}}}
or
{{{
$ setenv VERSIONER_PYTHON_VERSION 2.7 # C-like shells
}}}
This environment variable takes precedence over the preference file settings.
----
If you're using [[Macports|https://www.macports.org]], you can execute this to see what versions you have available:
{{{
$ port select --list python
Available versions for python:
none
python25-apple
python26-apple
python27 (active)
python27-apple
}}}
And to see which is active specifically:
{{{
port select --show python
The currently selected version for 'python' is 'python27'.
}}}
And to set the current version:
{{{
sudo port select --set python <the python version>
}}}
Couple different ways:
{{{
def same(items):
"""
items : list of objects.
return : bool : True \ False
"""
return all( [ items[0]==x for x in items[1:] ] )
}}}
{{{
def same(items):
"""
items : list of objects.
return : bool : True \ False
"""
ret = True
for i in items[1:]:
if i != items[0]:
ret = False
break
return ret
}}}
Maybe there is a fancier way to do this? I want to know if {{{data}}} contains a {{{subset}}}. I came up with two different ways:
{{{
data = [1,2,3,4,5,6]
subset = [3,4,5]
contains = len(subset) == len(set(subset).intersection(set(data)))
contains = len(subset) == len([item for item in subset if item in data])
# True
}}}
I ran this through a timer (10000x loops): the list comprehension method runs about 50% faster than the set.intersection solution.
However, I tracked down that if you pre-convert your lists to sets before you do the looping timer, the set.intersection solution ends up running 50% faster than the list comprehension.
You can use the string method {{{.join()}}} to do this:
{{{
foo = ["this", "is", "my", "list"]
sting = ' '.join(foo)
print sting
# this is my list
}}}
The characters in the string being created become the separators of the items of the list.
{{{
var = "this" if True else "that"
print var
# this
}}}
For some reason, I always forget how simple this is...
I did this as an exercise to wrap my head around decorators as well. It uses the [[time|http://docs.python.org/library/time.html]] module. There's also the [[timeit|http://docs.python.org/library/timeit.html]] module that has a lot of functionality.
The decorator object will execute the wrappered function 1000 times, print how long the whole operation took, and how long each loop took. The decorator also returns a list of [evaluationTime, functionName]. This allows you to profile many different functions, capture the return, and sort the results for which was fastest.
It should be noted that this code expects the functions being decorated to not return anything, since the decorator obviously returns it's own data and would hide anything the called function would.
{{{
import time
class Timer(object):
# Our Decorator
def __init__(self, f):
self.f = f
def __call__(self):
start = time.time()
for i in range(1000):
self.f()
end = time.time()
total = end - start
print ("Completed 1000 iterations of %s() in %.6f seconds, %.6f per loop"+
"")%(self.f.__name__, total, total/1000.0)
return [total, self.f.__name__]
@Timer
def stringAddA():
# Example function to time, wrapped in the decorator.
nums = [str(num) for num in range(1000)]
result = " ".join(nums)
@Timer
def stringAddB():
# Example function to time, wrapped in the decorator.
nums = range(1000)
result = ""
for i in range(len(nums)):
result += str(i)
}}}
{{{
speedTest = []
speedTest.append(stringAddA())
speedTest.append(stringAddB())
speedTest.sort()
for speed in speedTest:
print speed
}}}
{{{
Completed 1000 iterations of stringAddA() in 0.203000 seconds, 0.000203 per loop
Completed 1000 iterations of stringAddB() in 0.390000 seconds, 0.000390 per loop
[0.20300006866455078, 'stringAddA']
[0.3899998664855957, 'stringAddB']
}}}
----
Also see:
*[[Timer context manager]]
Python 2.6 and newer can use the {{{with}}} context manager, which is pretty slick, since it handles the file closing for you:
{{{
with open("c:/temp/foo.txt", "w") as f:
f.write("data\n")
}}}
Other ways:
{{{
f = open("c:/temp/foo.txt", "w")
f.write("data\n")
f.close()
}}}
{{{
p = "c:/temp/temp.txt"
t = ["line1\n", "line2\n", "line3\n"]
f = open(p, 'w')
f.writelines(t)
f.close()
}}}
http://docs.python.org/library/stdtypes.html#bltin-file-objects
The [[atexit|http://docs.python.org/library/atexit.html#module-atexit]] module allow for this: You can, via its [[register|http://docs.python.org/library/atexit.html#atexit.register]] function, have multiple functions be execute during exit.
[[sys.exitfunc|http://docs.python.org/library/sys.html#sys.exitfunc]] also provides for this, but only with a single function.
----
Example function that can be ran, that will write out a log file of the time Python was closed:
{{{
# makeExitLog.py
import os
import atexit
import datetime
logfile = os.path.join(os.getenv('TEMP'), 'pyCloseLog.txt')
def logWhenClose(*args):
"""
Will save a log file recording when Python was closed to the users TEMP dir,
which on Windows 7 is here: C:\Users\<userName>\AppData\Local\Temp
"""
date = datetime.datetime.now()
with open(logfile, "a") as f:
f.write("Python exited: %s\n"%date)
print "Wrote to exit log!"
def main():
atexit.register(logWhenClose)
}}}
{{{
$ python
>>> import makeExitLog
>>> makeExitLog.main()
>>> quit()
Wrote to exit log!
}}}
Then you can go open {{{C:\Users\<userName>\AppData\Local\Temp\pyCloseLog.txt}}} to confirm this.
objects come with a special attribute called {{{__module__}}} that holds the module name where the class was created. Furthermore, it returns back the full [[package|Packages]] path to the module, if the module is in a package.
{{{
# whereAmI.py, in the data package
class Spam(object):
def __init__(self):
print self.__module__
}}}
{{{
import data.whereAmI
eggs = whereAmI.Spam()
}}}
prints:
{{{
data.whereAmI
}}}
I found this out by poking around the [[inspect|http://docs.python.org/library/inspect.html#inspect.getmembers]] module.
----
Also see:
*[[Getting module save locations]]
Each index of {{{inspect.stack()}}} is a call level:
* {{{inspect.stack()[0][3]}}} : The name of the function calling {{{inspect.stack()}}}
* {{{inspect.stack()[1][3]}}} : The name of the parent function calling to {{{inspect.stack()}}} (if it exists)
* {{{inspect.stack()[2][3]}}} : The name of the grandparent function calling to {{{inspect.stack()}}} (if it exists)
* etc...
This example prints the name of the function calling to {{{inspect.stack()}}} directly:
{{{
import inspect
def getThisFuncName():
return inspect.stack()[0][3]
print getThisFuncName()
# getThisFuncName
}}}
This example creates a function that queries the name of the the function calling it:
{{{
import inspect
def getParentFuncName():
return inspect.stack()[1][3]
def myFunc():
print getParentFuncName()
myFunc()
# myFunc
}}}
Thanks to: http://stefaanlippens.net/python_inspect
https://docs.python.org/2/library/inspect.html#inspect.stack
You can combine the 'up a directory' syntax '{{{..}}}' combined with the module's {{{__file___}}} attribute wrappered in {{{os.path.join}}} and {{{os.path.realpath}}}:
{{{
# saved in c:/temp/foo/dirtest.py
import os
print "Module save dir:", os.path.realpath(os.path.join(__file__, '..'))
print "Up a dir:", os.path.realpath(os.path.join(__file__, '..', '..'))
}}}
{{{
C:\temp\foo>dirtest.py
Module save dir: C:\temp\foo
Up a dir: C:\temp
}}}
It's one thing for a module to go look and see where //another// module has been saved. But how can a module reference where itself has been saved? This is presuming these are modules authored by hand, and saved as {{{.py}}}.
''A few ideas:''
----
When a module is executed, you can use {{{sys.argv[0]}}} to find the full path of the executed module. Pass that into some {{{os}}} functions to find the absolute path.
Presuming both of these modules have been saved under {{{c:\stuff}}}:
{{{
# fileA.py
import sys
print "fileA.py:", os.path.dirname(os.path.abspath(sys.argv[0]))
}}}
{{{
# fileB.py
import sys
import fileA
print "fileB.py:", os.path.dirname(os.path.abspath(sys.argv[0]))
}}}
When {{{fileB.py}}} is executed:
{{{
fileA.py: c:\stuff
fileB.py: c:\stuff
}}}
I should note this isn't always true: I've queried this, and it actually returned the name of the executable that was launched //first// (Maya), then ran its own version of Python which called to my module... sigh....
----
I've used the special {{{__file__}}} attr with good success:
{{{
# c:\stuff\myModule.py
print os.path.abspath(__file__)
}}}
would print:
{{{
c:\stuff\myModule.py
}}}
If you want to get just the directory, here is some shorthand:
{{{
# c:/temp/test.py
import os
print os.path.realpath(os.path.join(__file__, '..'))
# or
print os.path.abspath(os.path.dirname(__file__))
}}}
would print:
{{{
c:/temp
}}}
----
Found [[this post|http://mail.python.org/pipermail/python-list/2003-December/242365.html]] describing a cleaver way to use [[inspect.getsourcefile|http://docs.python.org/library/inspect.html#inspect.getsourcefile]] and {{{lambda}}}.
{{{
# c:\stuff\myModule.py
import inspect
print inspect.getsourcefile(lambda:None)
}}}
would print:
{{{
c:\stuff\myModule.py
}}}
{{{getsourcfile}}}, as the name says, returns back the name of the module a piece of code was authored in, and {{{lambda}}} returns back an anonymous function inside of a given module.
----
Also see:
*[[How can I query where a module is saved?]]
*[[Getting module save locations]]
I wanted a way for a class to know when it was instanced, what the name of the calling module was. Here's one way to do it:
{{{
# inspectTest.py
import inspect
class Spam(object):
def __init__(self):
print "Spam initialized!"
print "\tMy module is:", __file__
lastCall = inspect.stack()[-1]
callingModule = lastCall[1]
print "\tCalling module is:", callingModule
}}}
When this module is then ran:
{{{
# someCallingModule.py
import inspectTest
s = it.Spam()
}}}
Prints
{{{
Spam initialized!
My module is: C:/temp/inspectTest.py
Calling module is: C:/temp/someCallingModule.py
}}}
You can call to the {{{object.__class__.__name__}}} attr:
{{{
class Spam(object):
def __init__(self):
print self.__class__.__name__
eggs = Spam()
}}}
{{{
Spam
}}}
{{{
x = input("Please enter a value")
}}}
Need to make the 'inner' sets {{{frozenset}}}:
{{{
s1 = frozenset([1,2,3])
s2 = frozenset([2,3,4])
s3 = frozenset([3,2,1])
uberSet = set([s1,s2,s3])
print(uberSet)
{frozenset({1, 2, 3}), frozenset({2, 3, 4})}
}}}
You can use the {{{try}}} statement \ {{{except}}} clause:
{{{
mylist = ["foo", "goo", "shoe"]
val = mylist.index("new")
# Traceback (most recent call last):
# File "<string>", line 1, in <string>
# ValueError: list.index(x): x not in list
}}}
As we can see, we've tried to access a value in {{{mylist}}} that doesn't exist, so Python raises a {{{ValueError}}}, which would stop the module\function from running. How to handle the exception:
{{{
try:
mylist = ["foo", "goo", "shoe"]
val = mylist.index("new")
except(ValueError):
print "Caught a exception, which was 'ValueError'."
# Caught a exception, which was 'ValueError'.
}}}
The {{{try}}} \ {{{except}}} catches the exception, and will allow the code to keep on running. There are many different types of exceptions that can be caught. The listed {{{ValueError}}} is singling out a specific type of exception for the user. If you don't want to be so specific, you can use just {{{except:}}}, which will catch any and all kinds of exceptions.
You can also catch the 'exception argument', which is the message Python tells you what is wrong when the exception occurs. Based on the above example, we'll change our exception handling to grab any type of exception, and report what it found. This is done via the {{{e}}} seen below.
{{{
try:
mylist = ["foo", "goo", "shoe"]
val = mylist.index("new")
except(Exception), e:
print "Caught an exception. This is what Python said:\n", e
# Caught an exception. This is what Python said:
# list.index(x): x not in list
}}}
----
''Here's a link to the full list of [[Built-In Exceptions|http://docs.python.org/library/exceptions.html]]''
----
Why, you may ask, are there so many different kinds of exceptions? For example, my scripting background is {{{MEL}}} (Maya Embedded Language), which has nothing so robust as Python for catching exceptions. In {{{MEL}}}, all you have is the generic {{{catch}}} command, which has the same general effect as calling to {{{except:}}} by itself. As I've leaned, by providing differnt types of exceptions to catch, it allows the user to tailor their code to behave differently when different problems are detected, rather than only being able to detect a simple success\failure state.
----
Also see:
*[[Understanding exceptions]]
{{{
import os
os.makedirs("c:/temp/foo/fooAgain")
# This will delete /fooAgain if it is empty, and it will also delete the parent dirs, if they're empty
}}}
{{{
import shutil
shutil.rmtree("c:/temp/foo")
}}}
{{{lerp}}}: 'linear interpolation': http://en.wikipedia.org/wiki/Lerp_(computing)
I can't seem to find this ability as a builtin in Python. How to do? I have this on my [[mel wiki|http://mayamel.tiddlyspot.com/]], but since t his is for Python, I should reproduce here:
Here's how it works:
{{{val1}}} and {{{val2}}} are the two values. {{{amt}}} is the percentage (from 0-1) between them you want to find the new value. If {{{amt}}} is {{{.5}}}, {{{lerp()}}} will return the value 50% between {{{val1}}} and {{{val2}}}:
{{{
def lerp(val1, val2, amt):
return val1 + (val2 - val1) * amt
print lerp(2, 16, .5)
# 9
}}}
----
And if you can lerp in 1d, why not 3d? Next section expands on the concept, but using 3d points rather than single values.
{{{p1}}} and {{{p2}}} are the two 3d points in space. {{{amt}}} is the percentage (from 0-1) between them you want to find the new point. If {{{amt}}} is {{{.5}}}, {{{lerp3D()}}} will return a point 50% between {{{p1}}} and {{{p2}}}:
{{{
def lerp3D(p1, p2, amt):
x = p1[0] + (p2[0] - p1[0]) * amt
y = p1[1] + (p2[1] - p1[1]) * amt
z = p1[2] + (p2[2] - p1[2]) * amt
return [x, y, z]
print lerp3d([2,2,2], [10,20,10], .25)
# [4.0, 6.5, 4.0]
}}}
----
Since color values are also expressed (usually) as three ints, you could use this code to {{{lerp}}} colors too:
{{{
print lerp3d([0,0,0], [255, 255, 255], .75)
# [191.25, 191.25, 191.25]
}}}
But, you'd need to convert those to {{{int}}}'s to be usable as color vals.
----
Also see:
*[[How can I find the percentage a value is between two other values?]]
This only works if the dir is empty:
{{{
import os
os.rmdir("c:/temp")
}}}
if you want to remove a directory, and all the stuff in it:
{{{
import shutil
shutil.rmtree("c:/temp")
}}}
{{{
import os
os.removedirs("c:/temp/foo")
}}}
{{{
import os
os.rename("c:/temp/renameFrom.txt", "c:/temp/renameTo.txt")
}}}
----
Also see:
*[[How can I rename a directory of files?]]
Good examples here
* https://stackoverflow.com/questions/580924/how-to-access-a-files-properties-on-windows
Pretty easy:
{{{
swapDict = dict((v,k) for k,v in myDict.items())
}}}
This of course can be dangerous if there are duplicate values.
{{{
import sys
for arg in sys.argv:
print arg
}}}
{{{sys.argv}}} is a list of all the arguments passed into the command. The first index 0 is the name of the script itself. For example, you have a script called "c:/tempreturnargs.py" with the above code, and you entered it into the command line with some random arguments, this is the result you'd get:
{{{
returnargs.py one two happy bob # --> the code we just entered at the prompt
c:/tempreturnargs.py #--> this is sys.argv[0]
one #--> this is sys.argv[1]
two #--> this is sys.argv[2], etc...
happy
bob
}}}
----
Also see:
*[[Capture command line arguments via argparse]]
PIL:
*[[Download|http://www.pythonware.com/products/pil/]]
*[[Docs|http://www.pythonware.com/library/pil/handbook/index.htm]]
The below example illustrates simple image manipulation: Save the given module, and drag images onto its icon: It will save out (in the same dir(s) as the source images) inverted version of them via the {{{Image.point}}} method:
{{{
# invertImage.py
import os, sys
from PIL import Image
def invertFunc(pixel):
pixel = 255 - pixel
return pixel
def main(image):
f, e = os.path.splitext(image)
outfile = "%s_invert.jpg"%f
inImg = Image.open(image)
outImg = inImg.point(invertFunc)
outImg.save(outfile)
print "Saved %s"%outfile
if __name__ == "__main__":
for image in sys.argv[1:]:
try:
main(image)
except Exception, e:
print "Failed:", e
raw_input("press enter to exit")
}}}
This article has a pretty good overview:
https://opensource.com/article/19/3/python-image-manipulation-tools
Update:
<<<
Recently found this blog post:
http://pysnippet.blogspot.com/2010/05/abcs-abstract-base-classes.html
That talks about the 'Abstract Base Class' module, which I was unaware of when authoring my system below. But they have similarities. [[docs|http://docs.python.org/library/abc.html]]
<<<
----
Interfaces are common in other languages like Java, but (to my knowledge) have no direct comparison in Python (there is a PEP for it [[here|http://www.python.org/dev/peps/pep-0245/]]). Interfaces are like classes that imply define the names of the attributes of what should exist, but don't define what they do. If a class implements an interface, they must implement all of the interfaces methods, etc, or you get failure. It's a way to maintain consistency and polymorphism in OOP. While reading a [[tutorial|http://www.javalobby.org/articles/jython/#Simulating%20interfaces%20with%20multiple%20inheritance]] for [[Jython|http://www.jython.org/]], I found a way to simulate this in Python (modified slightly from source):
{{{
class MyInterface(object):
def __init__(self):
if not hasattr(self, "myMethod"):
raise AttributeError("%s must implement myMethod"%self.__class__.__name__)
class MyClass(MyInterface):
def __init__(self):
MyInterface.__init__(self)
def myOtherMethod(self):
print "This will not fulfill the interface"
foo = MyClass()
}}}
{{{
AttributeError: MyClass must implement myMethod
}}}
While in Java interfaces are their own data types (like classes), in Python we simulate it by creating a class that when instanced, checks for given methods. If they don't exist, an exception is raised, since the interface wasn't fulfilled.
----
Also see:
*[[Abstract Methods]]
Python 3.5+, learned from [[HERE|https://stackoverflow.com/questions/67631/how-to-import-a-module-given-the-full-path]].
* https://docs.python.org/3/library/importlib.html#module-importlib.util
** https://docs.python.org/3/library/importlib.html#importlib.util.spec_from_file_location
** https://docs.python.org/3/library/importlib.html#importlib.machinery.ModuleSpec
{{{
import importlib.util
modulePath = "c:/some/path/to/my/awesomeModule.py"
spec = importlib.util.spec_from_file_location("awesomeModule", modulePath) # type: ModuleSpec
myModule = importlib.util.module_from_spec(spec) # type: module
spec.loader.exec_module(myModule)
print(myModule.rigSaveFile)
}}}
----
Also see:
* [[Absolute module imports]]
Three main ways to initialize a superclass from a subclass:
Here are high level differences between Python 2 & 3. Note, all options work in Python 3, but calling to the top solution is suggested.
{{{
class SomeSubClass(SuperClass):
__init__(self, *args, **kwargs):
# Python 3
super().__init__(*args, **kwargs)
# New Python 2
super(SomeSubClass, self).__init__(*args, **kwargs)
# Old Python 2
SuperClass.__init__(self, *args, **kwargs)
}}}
!On the mac
Has been a nightmare. Lion 10.7.5, and Xcode 4.5.2
!!Numpy:
Built source and installed via (all) the instructions here:
http://www.scipy.org/Installing_SciPy/Mac_OS_X
Amazingly, worked.
!!Scipy
!!!!FAIL SECTION:
{{{
$ pip install scipy
}}}
{{{
error: library dfftpack has Fortran sources but no Fortran compiler found
}}}
(and yes, I installed that compiler via the notes on [[this page|http://www.scipy.org/Installing_SciPy/Mac_OS_X]], restarted)
----
Build from source via this link:
http://www.scipy.org/Installing_SciPy/Mac_OS_X
{{{
error: library dfftpack has Fortran sources but no Fortran compiler found
}}}
----
Via the "Scipy Superpack":
http://fonnesbeck.github.com/ScipySuperpack/
This installed Numpy, but scipy failed
!!!!WIN SECTION:
Via the installer {{{scipy-0.11.0-py2.7-python.org-macosx10.6.dmg}}} located in Sourceforge here:
http://sourceforge.net/projects/scipy/files/scipy/0.11.0/
That one worked after I tried all the above stuff, so maybe some of all those other installs helped contribute to it's success.
!!Matplotlib
{{{
pip install matplotlib
}}}
Worked on the first try. WHAT?!?!
What... a nightmare....
I have Python 2.6 installed on Lion 10.7.5. On the PC it's a snap to get PIL installed. But on the mac... I kept getting this thing about missing the {{{_imaging}}} library. And when I'd download the PIL source and try to build, I'd constantly get something like "gcc4.0 not in path". Long story short: All sorts of building magic had to happen, and I could only get it to work via building PIL via [[Macports|http://www.macports.org/]]. Of course, I don't know anything about Macports, so this web post hooked me up:
http://parezcoydigo.wordpress.com/2011/05/31/installing-pil-on-snow-leopard/
Important stuff from it copied here for safety:
----
#1 Re-install libjpeg with Macports and adding the +universal argument to the command:
{{{
$ sudo port install jpeg +universal
}}}
#2 Install PIL with Macports in the same manner:
{{{
$ sudo port install py26-pil +universal.
}}}
----
Probably took half an hour building all the dependencies on my Macbook Air, but when it was done I coped the data from here:
{{{
/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/PIL
}}}
to:
{{{
/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/PIL
}}}
And amazingly, it worked. I'm seriously amazed. The Mac really sucks for some things....
NOTE: This is info for a more 'vanilla' system-level install of Python. Since having done this, I've adopted Miniconda, and would highly recomend anyone use that to manage their Python, and their packages instead. See info here: [[closeclose otherseditmore
Anaconda Fundamentals]]
But if not the Anaconda family, use {{{pip}}}. And if that fails, try to "Install from source".
!pip
[[pip|http://www.pip-installer.org]] makes it really easy to instal Python packages directly from [[PyPi|http://pypi.python.org/pypi]]
{{{pip}}} is actually a wrapper for {{{setuptools}}} (see below). You'll need to have that installed first before pip can be installed. Mac & Linux systems should already have it installed, but Windows people will need to download the latest executable installer from [[here|http://pypi.python.org/pypi/setuptools#files]]
{{{pip}}} installation instructions [[here|https://pip.pypa.io/en/latest/installation/]]
But really, it should be included with all new Python installs.
----
To install new packages with pip, there are two main approaches: Call to pip on the commandline, or have a specific python.exe call //to/// pip to do the install : The later is far safer, since if you call to pip "on it's own", and you have multiple versions of Python installed, you can't guarantee which one it will find (based on your PATH) and run. So below, we'll show the 'python.exe' version of running pip.
For the 'active' version of Python (what the system thinks the current version is, since you can have multiple versions installed), you can now easily install packages. For example, if you have Python 2.6 installed, running this code will install the package into that versions {{{/site-packages}}} directory (well, usually that dir).
CD into the dir where the python.exe lives that you want to install a new package for:
{{{
> cd C:\Users\Eric\AppData\Local\Programs\Python\Python38
}}}
Confirm you have pip: This will auto-install it if you don't:
{{{
> python -m ensurepip --upgrade
}}}
And feel free to upgrade it too:
{{{
> python -m pip install --upgrade pip
}}}
Now, have Python call to pip to do the install:
{{{
> python -m pip install numpy
}}}
Or if you already have it installed, and want to upgrade it (or if you've installed a new version of Python and want to reinstall previously installed packages in the new Python version):
{{{
$ python -m pip install numpy --upgrade
}}}
To see all the packages {{{pip}}} has installed, you can do a:
{{{
> python -m pip freeze
}}}
or
{{{
> python -m pip list
}}}
You can also limit {{{pip}}} to query only a specific version of Python:
You can use this same syntax when updating\installing packages, for a specific version of Python, rather than the 'current' version.
{{{
> python -m pip-2.7 freeze
}}}
To see which packages are out of date:
{{{
> python -m pip list --outdated
}}}
Search pip (NOTE, this appearst to be deprecated, maybe just search the website manually?)
{{{
> python -m pip search <packageName>
}}}
!Install from source using setup.py
Often times when getting the //source// of a package (from say [[PyPi|http://pypi.python.org/pypi]]), you'll find a {{{setup.py}}} file in the root dir. What to do? From the install dir that contains {{{setup.py}}}:
It's a good idea to provide the full path to the python.exe you want to install for here:
{{{
> python setup.py install
}}}
And this will work all the magic to install and configure the package.
This is just like the PC install example above for {{{pip}}}.
{{{setup.py}}} files themselves are covered in the [[distutils docs|http://docs.python.org/distutils/setupscript.html]]
!setuptools & easy_install:
Really, you should just use {{{pip}}}, which is a wrapper around setuptools (see above).
setuptools is the name of the program, and {{{easy_install}}} is the name of the command you execute to do stuff.
For the longest time I heard about 'Python Eggs'... and this is where it lead me:
*Download and install {{{setuptools}}}:
**http://pypi.python.org/pypi/setuptools#downloads
**This also installs {{{easy_install}}} in {{{\site-packages}}}
*Read the docs! :)
**http://peak.telecommunity.com/DevCenter/EasyInstall
*Other notes:
**On Windows, an {{{easy_install.exe}}} application will be installed in your {{{c:\PythonXX\Scripts}}} dir. Make sure that dir is part of Window's path, so you can execute it.
Using {{{easy_install}}} is pretty straightforward (when it works). From a shell:
{{{
$ easy_install <package name>
}}}
And it will go off and search [[PyPi|http://pypi.python.org/pypi]] for the {{{<package name>}}} and install it.
FYI, {{{.egg}}} files are really just zips, so if you want to look inside, use the unzipper you're most comfortable with.
<<gradient horiz #ddddff #ffffff >>This is a [[TiddlyWiki|http://tiddlywiki.com/]]. To really get a grasp on how to navigate it, check out their [[homepage|http://tiddlywiki.com/]]. Quick directions below:
----
''SEARCHING FOR DATA:''
#Browse the "Tags" tab in the //right column// for Python-ish key-words.
**Inside the Tags tab, major ''Categories'' are all in caps, like "[[ENVIRONMENT]]".
**When picking a 'Tag' with more than one link, you can either:
###'{{{Open all}}}' the topics in that Tag (meaning, fully expand all the topics listed in the middle of that pop-up menu).
###Open a single topic by picking its heading.
###Show all the headings in the Tag by picking: {{{Open tag 'tagname}}}'.
#Use your web browsers screen-search ability ('Ctrl+F' in both Firefox & Internet Explorer) to find key-words you're after (good if 'Tags' tab is open).
#Or start browsing from the ''Categories'' section in the //left column//. This will open each of their major headings in a new tiddler.
If things get too crowded, use the "close all" from the //right column// to clean up the page. Or, you can use "close others" from an individual tiddler (This block called "[[Instructions For Use]]" is a tiddler, for example).
----
''COPYING DATA FROM WIKI, TO PYTHON:''
*The way the text has been entered into this wiki, copying code from the source-boxes should work:
{{{
source-code in a box;
}}}
*Other times it's not in a box, but is still safe for copy:
{{{source-code not in a box, but still safe to copy;}}}
*If you copy any code outside of a box that's 'not safe', Python //may// have a hard time with it's formatting and be angered. Weird>>
https://www.tiltbrush.com/
! Install the tools:
You can download the toolkit here:
https://github.com/googlevr/tilt-brush-toolkit
I installed mine here: (replace {{{<USERNAME>}}} with yours) :
{{{
C:\Users\<USERNAME>\Documents\git\tilt-brush-toolkit-master
}}}
Then added this file to Python:
{{{
C:\Python27\tiltbrush.pth
}}}
with this line in it:
{{{
C:\Users\<USERNAME>\Documents\git\tilt-brush-toolkit-master\Python
}}}
! Finding Data:
All data is saved under:
{{{
C:\Users\<USERNAME>\Documents\Tilt Brush
}}}
* {{{\Media Library}}} : Data importable into the Tilbrush VR app (external models, etc)
* {{{\Sketches}}} : *.tilt files
* {{{\Snapshots}}} : *.png & *.gif (animated)
* {{{\Videos}}} : *.mg4 files
Python has nice indexed\searchable help app (presuming you've [[downloaded\installed|http://www.python.org/doc/]] Python's current documentation). Here is an example of it's save location:
{{{
C:\Python25\Doc\Python25.chm
}}}
I have a shortcut to that on my desktop.
----
You can also launch {{{pydocgui.pyw}}} from the system:
{{{
C:\Python<version>\Tools\Scripts\pydocgui.pyw
}}}
This will open a nice graphical user interface that lets the user search for functions, classes, etc. And, it will open a web-browser with the results. If you want to launch this from your IDE, you can just {{{import pydoc}}}:
{{{
import pydoc
pydoc.gui()
}}}
Note: As it turns out [[JupyterLab : Overview]] is the newer branch: Should probably start using it instead.
You can also run Jupyter notebooks in : https://colab.research.google.com/
All examples below are via a Conda environment
! Install Jupyter
If you didn't install Jupyter when you setup your Conda environment:
* Following the steps here: [[Anaconda Fundamentals]], activate your environment.
* Then, install Jupyter via the Conda terminal/shell:
{{{
conda install jupyter
}}}
! Run A Jupyter Notebook
* Following the steps here: [[Anaconda Fundamentals]], activate your environment.
* Make sure you're in the root project dir, and not the {{{\env}}} subdir, and to open the Jupyter Notebook desktop:
* {{{> jupyter notebook}}}
* This should open a web-browser to your local host: {{{http://localhost:8888/tree}}}
* It will save with a {{{.ipynb}}}, the old format 'Iron Python (C#?) Notebook'
! Navigate The Jupyter Notebook Dashboard
* Access the Jupyter Dashboard per above
* Files:
** View of the local filesystem where the notebook was opened.
** If you already have Jupyter Notebook(s) for this project, you'll see them here, and you can open them.
** Expected to be project root: This is where your Jupyter notebooks are saved, and your data files go.
* Running:
** This shows any Jupyter Notebooks that are currently running.
** You can 'close' them here too, but it's easier to just {{{ctrl+c}}} in the Conda terminal.
* Upload:
** Uploads (local file copy) data into this dir.
* New
** Allows you to create a new Jupyter Notebook (or text files, folders, terminals)
! Navigate A Jupyter Notebook
* Notebook can be in two modes:
** Edit Mode :
*** You'll see a little 'pencil' up in the top right corner, and each cel has a green border.
*** Activated by pressing Enter.
** Command Mode :
*** No 'little pencil', and the cells will have a blue border
*** Activated by pressing 'Esc'.
!! Edit Mode Features
* This is where you do all your coding.
* Note, you can print data for display just by evaluating the variable name, no need to 'print()'
* Enter gives a new line of code
* Shift+Enter Evaluates that cel.
* Ctrl+Enter : Evaluate selected cels.
* pressing Shift+tab while inside a function call: {{{myFunction(shift+tab)}}} will bring up the docstring.
* {{{%matplotlib inline}}} : This tells the notebook to place any graphs made by that module to be physically displayed //in// the notebook, an not a separate window.
!! Command Mode Features
* Can change a cell between 'code' (y) and 'markdown' (m)
* Markdown can be used to insert informative text and images into your notebook:
** {{{# This Is A Main Heading}}}
** {{{## This is as sub-heading}}}
** {{{![](displayThisImage.png)}}}
** {{{<img src="displayThisImage.png"/>}}}
* Add a new cel above (a), and below (b).
* Delete a cel (dd)
* You can run terminal commands directly in Command Mode as well:
** {{{ls}}}
*** But in some cases, you need to use an excalamation point first (if the terminal command collides with a Python function): {{{!dir}}}
* Save your notebook (s)
! Shutdown A Notebook:
* Generally, just {{{ctrl+c}}} in the Conda terminal that created it.
! Special Commands
Maybe a function fails in your Jupyter notebook, requiring some other library: You can do something like this:
{{{
%matplotlib inline
import matplotlib.pyplot as plt
}}}
Timing operations:
{{{
%timeit sum(some_array)
}}}
! Working in the cloud:
https://colab.research.google.com/
These can be ran/saved directly from your Google Drive.
Note: This skips the Miniconda installation step on your local PC, since the colab environment comes pre-installed with all that stuff.
What is it?
* ~JupyterLab is the next generation of the Jupyter Notebook. ... ~JupyterLab uses the exact same Notebook server and file format as the classic Jupyter Notebook, so that it is fully compatible with the existing notebooks and kernels. The Classic Notebook and Jupyterlab can run side to side on the same computer.
Docs:
* https://jupyterlab.readthedocs.io/en/stable/
* https://jupyterlab.readthedocs.io/en/stable/getting_started/installation.html
Install via Conda:
{{{
conda install -c conda-forge jupyterlab
}}}
Other Web:
* https://www.reddit.com/r/learnmachinelearning/comments/jzi1p3/hidden_features_in_jupyterlab/
* https://towardsdatascience.com/5-hidden-features-in-jupyterlab-you-should-start-using-bfd9402464ca
To run it:
Open a Conda terminal and activate your environment per: [[Anaconda Fundamentals]]
{{{
> jupyter lab
}}}
Opens on localhost here:
{{{
http://localhost:8888/lab
}}}
In the 'default workspace'.
Print all the Python keywords:
{{{
import keyword
for kw in keyword.kwlist:
print kw
}}}
Also includes a handy {{{iskeyword()}}} function.
http://docs.python.org/library/keyword.html
http://kivy.org/docs/api-kivy.app.html
The App class is the base for creating Kivy applications. Think of it as your main entry point into the Kivy run loop. In most cases, you subclass this class and make your own app. You create an instance of your specific app class and then, when you are ready to start the application’s life cycle, you call your instance’s App.run() method.
To initialize your app with a widget tree, override the {{{build()}}} method in your app class and return the widget tree you constructed.
Events
*{{{on_start}}} : Fired when the application is being started (before the runTouchApp() call.
*{{{on_stop}}} : Fired when the application stops.
*{{{on_pause}}] : Fired when the application is paused by the OS.
*{{{on_resume}}} :Fired when the application is resumed from pause by the OS. Beware: you have no guarantee that this event will be fired after the on_pause event has been called.
{{{__init__}}} parameters :
*{{{kv_directory}}}: <path>, defaults to None
**If a kv_directory is set, it will be used to get the initial kv file. By default, the file is assumed to be in the same directory as the current App definition file.
*{{{kv_file}}}: <filename>, defaults to None
**If a kv_file is set, it will be loaded when the application starts. The loading of the “default” kv file will be prevented.
Methods:
*{{{build()}}} : Initializes the application; will be called only once. If this method returns a widget (tree), it will be used as the root widget and added to the window. Returns {{{None}}} or a root Widget instance if no self.root exists.
*{{{build_config(config)}}} : This method is called before the application is initialized to construct your {{{ConfigParser}}} object.
*{{{build_settings(settings)}}} : This method is called when the user (or you) want to show the application settings.
*{{{close_settings(*largs)}}} : Close the previously opened settings panel.
*{{{create_settings()}}} : Create the settings panel. This method is called only one time per application life-time and the result is cached internally.
*{{{destroy_settings()}}} : Dereferences the current settings panel if one exists.
*{{{directory}}} : Return the directory where the application lives.
*{{{display_settings(settings)}}} : Display the settings panel. By default, the panel is drawn directly on top of the window.
*{{{get_application_config(defaultpath='%(appdir)s/%(appname)s.ini')}}} : Return the filename of your application configuration.
*{{{get_application_icon()}}} : Return the icon of the application.
*{{{get_application_name()}}} : Return the name of the application.
*{{{icon}}} : Icon of your application. Class attr.
*{{{load_config()}}} : (internal) This function is used for returning a {{{ConfigParser}}} with the application configuration.
*{{{load_kv(filename=None)}}} : This method is invoked the first time the app is being run if no widget tree has been constructed before for this app.
*{{{name}}} : Return the name o the application based on the class name.
*{{{on_config_change(config, section, key, value)}}} : Event handler fired when a configuration token has been changed by the settings page.
*{{{on_pause()}}} : Event handler called when Pause mode is requested.
*{{{on_resume()}}} : Event handler called when your application is resuming from the Pause mode.
*{{{on_start()}}} : Event handler for the on_start event which is fired after initialization (after build() has been called) but before the application has started running.
*{{{on_stop()}}} : Event handler for the on_stop event which is fired when the application has finished running (i.e. the window is about to be closed).
*{{{open_settings(*largs)}}} : Open the application settings panel.
*{{{options}}} : Options passed to the __init__ of the App.
*{{{root}}} : Root widget set by the build() method or by the load_kv() method if the kv file contains a root widget.
*{{{run()}}} : Launches the app in standalone mode.
*{{{settings_cls}}} : The class to used to construct the settings panel and the instance passed to build_config().
*{{{stop(*largs)}}} : Stop the application.
*{{{title}}} : Title of your application. Class attr.
*{{{use_kivy_settings}}} : If True, the application settings will also include the Kivy settings.
*{{{user_data_dir}}} : Returns the path to the directory in the users file system which the application can use to store additional data.
Static Methods:
*{{{get_running_app()}}} : Return the currently running application instance.
Notes as I learn it
----
* Main page: http://kivy.org/
* Main Docs: http://kivy.org/docs/
** API Docs : http://kivy.org/docs/api-kivy.html
** API Index: http://kivy.org/docs/api-index.html
* Architecture Overview : http://kivy.org/docs/guide/architecture.html
http://kivy.org/docs/api-kivy.graphics.instructions.html?highlight=canvas#kivy.graphics.instructions.Canvas
The Canvas is the root object used for drawing by a [[Widget|Kivy : Widget]]. Use this class to add graphics or context instructions that you want to be used for drawing.
Note: The Canvas supports Python’s with statement and its enter & exit semantics.
Without {{{with}}}:
{{{
self.canvas.add(Color(1., 1., 0))
self.canvas.add(Rectangle(size=(50, 50)))
}}}
With {{{with}}}:
{{{
with self.canvas:
Color(1., 1., 0)
Rectangle(size=(50, 50))
}}}
Properties:
*{{{after}}} : Property for getting the ‘after’ group.
*{{{before()}}} : Property for getting the ‘before’ group.
*{{{has_after}}} : Property to see if the canvas.after is already created
*{{{has_before}}} : Property to see if the canvas.before is already created
*{{{opacity}}} : Property for get/set the opacity value of the canvas.
Methods:
*{{{ask_update()}}} : Inform the canvas that we’d like it to update on the next frame. This is useful when you need to trigger a redraw due to some value having changed for example.
*{{{clear()}}} : Clears every Instruction in the canvas, leaving it clean.
I couldn't get any kivy apps to run\debug in Wing on my Mac. I'd constantly get exceptions:
{{{
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/kivy/core/window/window_pygame.py", line 180, in set_icon
im = pygame.image.load(filename)
error: File is not a Windows BMP file
}}}
As it turns out, I needed to change this function in {{{window_pygame.py}}}:
{{{
def set_icon(self, filename):
try:
if not exists(filename):
return False
try:
im = pygame.image.load(filename)
except UnicodeEncodeError:
im = pygame.image.load(filename.encode('utf8'))
if im is None:
raise Exception('Unable to load window icon (not found)')
pygame.display.set_icon(im)
super(WindowPygame, self).set_icon(filename)
except:
Logger.exception('WinPygame: unable to set icon')
}}}
To this:
{{{
def set_icon(self, filename):
im = None
try:
if not exists(filename):
return False
try:
im = pygame.image.load(filename)
except:
pass
if im:
pygame.display.set_icon(im)
super(WindowPygame, self).set_icon(filename)
except:
Logger.exception('WinPygame: unable to set icon')
}}}
Try to load the image. If it fails, who cares?
http://kivy.org/docs/api-kivy.core.image.html
"Core classes for loading images and converting them to a [[Texture|Kivy : Texture]]. The raw image data can be keep in memory for further access."
Image class info:
{{{
Image(arg, keep_data=False, scale=1.0, mipmap=False, anim_delay=.25)
}}}
{{{__init__}}} parameters:
*{{{arg}}} : can be a string (str), [[Texture|Kivy : Texture]] or {{{Image}}} object.
**A string is interpreted as a path to the image to be loaded. You can also provide a texture object or an already existing image object. In the latter case, a real copy of the given image object will be returned.
*{{{keep_data}}} : bool, defaults to False.
**Keep the image data when the texture is created.
*{{{scale}}} : float, defaults to 1.0
**Scale of the image.
*{{{mipmap}}} : bool, defaults to False
**Create mipmap for the texture.
*{{{anim_delay}}}: float, default to .25
**Delay in seconds between each animation frame. Lower values means faster animation.
Methods:
*{{{anim_available}}} : Return True if this Image instance has animation available.
*{{{anim_delay}}} : Delay between each animation frame. A lower value means faster animation.
*{{{{anim_index}}} : Return the index number of the image currently in the texture.
*{{{anim_reset(allow_anim)}}} : Reset an animation if available.
*{{{filename}}} : Get/set the filename of image
*{{{hight}}} : Image height
*{{{image}}} : Get/set the data image object
*{{{nocache}}} : Indicate whether the texture will not be stored in the cache or not.
*{{{on_texture(*largs)}}} : This event is fired when the texture reference or content has changed. It is normally used for sequenced images.
*{{{read_pixel(x, y)}}} : For a given local x/y position, return the pixel color at that position. This function can only be used with images loaded with the keep_data=True keyword.
*{{{remove_from_cache()}}} : Remove the Image from cache. This facilitates re-loading of images from disk in case the image content has changed.
*{{{save(filename)}}} : Save image texture to file. The filename should have the ‘.png’ extension because the texture data read from the GPU is in the RGBA format. ‘.jpg’ might work but has not been heavilly tested so some providers might break when using it. Any other extensions are not officially supported.
*{{{size}}} : Image size (width, height)
*{{{texture}}} : Texture of the image.
*{{{width}}} : Image width.
Static Methods:
*{{{load(filename **kwargs)}}} : Load an image.
http://kivy.org/docs/api-kivy.graphics.texture.html
Texture is a class to handle ~OpenGL texture. Depending of the hardware, some ~OpenGL capabilities might not be available (BGRA support, NPOT support, etc.)
You cannot instanciate the class yourself. You must use the function Texture.create() to create a new texture:
{{{
texture = Texture.create(size=(640, 480))
texture = Texture.create(size=(640, 480), colorfmt='rgba')
}}}
You can create your own data and blit it on the texture using {{{Texture.blit_data()}}}. See above link.
Methods:
*{{{add_reload_observer()}}} : Add a callback to be called after the whole graphics context have been reloaded. This is where you can reupload your custom data in GPU.
*{{{ask_update()}}} : Bind the texture to current opengl state.
*{{{blit_buffer()}}} : Blit a buffer into a texture.
*{{{blit_data()}}} : Replace a whole texture with a image data
*{{{bufferfmt}}} : Return the buffer format used in this texture. (readonly)
*{{{colorfmt}}} : Return the color format used in this texture. (readonly)
*{{{create()}}} : Create a texture based on size. Parameters:
**{{{size}}} : tuple, default to (128, 128)
**{{{colorfmt}}} : str, default to ‘rgba’
** {{{bufferfmt}}} : str, default to ‘ubyte’
** {{{mipmap}}}: bool, default to False
** {{{callback}}} : callable(), default to False
* {{{create_from_data()}}} : Create a texture from an ImageData class
* {{{flip_vertical()}}} : Flip tex_coords for vertical displaying
* {{{get_region()}}} : Return a part of the texture defined by the rectangle arguments (x, y, width, height). Returns a TextureRegion instance.
* {{{height}}} : Return the height of the texture (readonly)
* {{{id}}} : Return the OpenGL ID of the texture (readonly)
* {{{mag_filter}}} : Get/set the mag filter texture.
* {{{min_filter}}} : Get/set the min filter texture.
* {{{mipmap}}} : Return True if the texture have mipmap enabled (readonly)
* {{{pixels}}} : Get the pixels texture, in RGBA format only, unsigned byte.
* {{{remove_reload_observer()}}} : Remove a callback from the observer list, previously added by add_reload_observer().
* {{{save()}}} : Save the texture content into a file. Check kivy.core.image.Image.save() for more information about the usage.
* {{{size}}} : Return the (width, height) of the texture (readonly)
* {{{target}}} : Return the OpenGL target of the texture (readonly)
* {{{tex_coords}}} : Return the list of tex_coords (opengl)
* {{{uvpos}}} : Get/set the UV position inside texture
* {{{uvsize}}} : Get/set the UV size inside texture.
* {{{width}}} : Return the width of the texture (readonly)
* {{{wrap}}} : Get/set the wrap texture.
http://kivy.org/docs/api-kivy.uix.widget.html
The Widget class is the base class required to create a Widget. This widget class is designed with a couple of principles in mind:
*Event Driven
*Separate the widget and its graphical representation. Widgets don’t have a draw() method. This is done on purpose: The idea is to allow you to create your own graphical representation outside the widget class.
*Bounding Box / Collision
Events :
* {{{on_touch_down}}} : Fired when a new touch event occurs.
* {{{on_touch_move}}} : Fired when an existing touch moves.
* {{{on_touch_up}}} : Fired when an existing touch disappears
Methods:
*{{{add_widget(widget, index=0)}}} : Add a new widget as a child of this widget.
*{{{clear_widgets(children=None)}}} : Remove all widgets added to this widget.
*{{{collide_point(x, y)}}} : Check if a point (x, y) is inside the widget’s axis aligned bounding box.
*{{{collide_widget(wid)}}} : Check if the other widget collides with this widget. Performs an axis-aligned bounding box intersection test by default.
*{{{get_parent_window()}}} : Return the parent window.
*{{{get_root_window()}}} : Return the root window.
*{{{on_touch_down(touch)}}} : Receive a touch down event.
*{{{on_touch_move(touch)}}} : Receive a touch move event.
*{{{on_touch_up(touch)}}} : Receive a touch up event.
*{{{remove_widget(widget)}}} : Remove a widget from the children of this widget.
*{{{to_local(x, y, relative=False)}}} : Transform parent coordinates to local coordinates.
*{{{to_parent(x, y, relative=False)}}} : Transform local coordinates to parent coordinates.
*{{{to_widget(x, y, relative=False)}}} : Convert the given coordinate from window to local widget coordinates.
*{{{to_window(x, y, initial=True, relative=False)}}} : Transform local coordinates to window coordinates.
Attributes:
*{{{canvas}}} : Canvas of the widget.
*{{{center}}} : Center position of the widget.
*{{{center_x}}} : X center position of the widget.
*{{{center_y}}} : Y center position of the widget.
*{{{children}}} : List of children of this widget.
*{{{cls}}} : Class of the widget, used for styling.
*{{{disabled}}} : Indicates whether this widget can interact with input or not.
*{{{height}}} : Height of the widget
*{{id}}} : Unique identifier of the widget in the tree.
*{{{ids}}} : This is a Dictionary of id’s defined in your kv language. This will only be populated if you use id’s in your kv language code.
*{{{opacity}}} : Opacity of the widget and all the children.
*{{{parent}}} : Parent of this widget.
*{{{pos}}} : Position of the widget.
*{{{pos_hint}}} : Position hint. This property allows you to set the position of the widget inside its parent layout, in percent (similar to size_hint).
*{{{proxy_ref}}} : Return a proxy reference to the widget, i.e. without creating a reference to the widget.
*{{{right}}} : Right position of the widget.
*{{{size}}} : size of the widget.
*{{{size_hint}}} : size hint
*{{{size_hint_x}}} : X size hint. Represents how much space the widget should use in the direction of the X axis relative to its parent’s width.
*{{{size_hint_y}}} : Y size hint.
*{{{top}}} : Top position of the widget
*{{{width}}} : With of the widget.
*{{{x}}} X position of the widget.
*{{{y}}} Y position of the widget.
To download \ install the Kivy app, you can do that directly from their web page here: http://kivy.org/#download
This will allow you to run a kivy Python file from the command line like so:
{{{
$ kivy myKivyApp.py
}}}
But to actually get the source installed, so you can use the libraries in your own IDE, it requires more hoop jumping:
It requires [[Cython|http://cython.org/]] however, so you'll need to make sure that's installed first.
To do this, I used [[pip|Installing Python Packages]]:
{{{
$ pip install cython
}}}
To get Kivy's source, download the from Github: https://github.com/kivy/kivy (I downloaded the zip)
After unzipping it, browse to the folder and install from source:
{{{
$ python setup.py install
}}}
That was about it. I can now:
{{{
$ python
>>> import kivy
[INFO ] Kivy v1.5.2-dev
}}}
On the Mac, it installed the library here:
{{{
/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/kivy
}}}
*http://archlinux.me/dusty/2013/06/13/creating-an-application-in-kivy-part-1/
!Machine Learning University
* Blerb about it: https://towardsdatascience.com/amazon-wants-to-make-you-an-ml-practitioner-for-free-552c46cea9ba
* Main ~YouTube page: https://www.youtube.com/channel/UC12LqyqTQYbXatYS9AA7Nuw
* The ~GitHub pages for the courses:
** https://github.com/aws-samples/aws-machine-learning-university-accelerated-nlp
** https://github.com/aws-samples/aws-machine-learning-university-accelerated-cv
** https://github.com/aws-samples/aws-machine-learning-university-accelerated-tab
----
* [[How I’d study machine learning — if I’d be starting out today|https://thenextweb.com/neural/2020/10/16/how-id-study-machine-learning-if-id-be-starting-out-today-syndication/]]
** The course he teaches based on that article: https://www.mrdbourke.com/mlcourse/
** https://academy.zerotomastery.io/p/complete-machine-learning-and-data-science-bootcamp-zero-to-mastery?affcode=441520_izj92
** Phase 1 : Python, NumPy, pandas, scikit-learn, https://jupyter.org/, https://www.elementsofai.com/, https://www.pythonlikeyoumeanit.com/ (Python + numpy), https://www.3blue1brown.com/essence-of-linear-algebra-page/, https://mml-book.github.io/
*** Plus these extras: https://www.freecodecamp.org/, https://cs50.harvard.edu/college/2020/fall/, https://cs50.harvard.edu/college/2020/fall/, https://missing.csail.mit.edu/, https://www.amazon.com/gp/product/1492032646/
** Phase 2: https://www.fast.ai/,https://www.deeplearning.ai/, https://course.fullstackdeeplearning.com/
Rather than just retype it all, might as well use the actual docs ;)
http://docs.python.org/lib/typesseq-mutable.html 'Mutable Sequence Types'
and
http://docs.python.org/tut/node7.html 'Data Structures'
''Hilights'':
*List methods (also see [[List methods]])
*Lists as Stacks
*Using Lists as Queues
*Functional Programming Tools:
**Filter
**Map
**Reduce
*List Comprehensions
*The del statement
*Tuples and Sequences
*Sets
*Dictionaries
*Looping Techniques
*Comparing Sequences and Other Types
''Tips & Tricks:''
----
How can I remove duplicates from a list?
<<tiddler [[How can I remove duplicates from a list?]]>>
----
If you want to make a ''copy of a list'', this is how you //shouldn't// do it:
{{{
listA = ["a","b","c"]
listB = listA
if listA is listB:
print "true!"
# true!
}}}
In this case, the variable name {{{listA}}} and {{{listB}}} are both poting to the exact same place in memory, which holds the data {{{["a","b","c"]}}}. This is proven by using the {{{is}}} test in the above example.
To properly make a copy, you can grab a slice, which happens to be the whole list:
{{{
listA = ["a","b","c"]
listB = listA[:]
}}}
If you want to make a //reversed// copy:
{{{
listB = listA[::-1]
}}}
----
{{{
a = [1, 2, 3]
b = [4, 5, 6]
}}}
Add lists:
{{{
c = a + b
print c
# [1, 2, 3, 4, 5, 6]
}}}
Zip lists (returns list of tuples):
{{{
d = zip(a,b)
print d
[(1, 4), (2, 5), (3, 6)]
}}}
Map lists (using lambda).
Will multiply each element of list a against list b:
{{{
e = map(lambda x, y: x*y, a,b)
print e
# [4, 10, 18]
}}}
----
Full copy:
{{{
copy.deepcopy(X)
list(L)
}}}
Insert items at front of list L:
{{{
L[:0] = [X,Y,Z,]
}}}
Insert multiple items at the end of list L, in-place:
{{{
L[len(L):] = [X,Y,Z]
L.extend([X,Y,Z]
L += [ X,Y,Z]
}}}
Implement in-place stack operations, where the end of the list is the top of the stack:
{{{
L.append(X)
X=L.pop()
}}}
Indexing:
{{{
# first item in the list:
S[0]
# last item in the list:
S[-1]
# slice list from offsets 1-3:
S[1:4]
# slice everything after the first
S[1:]
# slice everything but the last:
S[:-1]
# Make a copy of list
S[:]
}}}
http://docs.python.org/tut/node7.html
{{{
>>> listFoo = ["this", "is", "a", "list"]
>>> for thing in dir(listFoo):
>>> print thing
append
count
extend
index
insert
pop
remove
reverse
sort
}}}
{{{
\a # Sounds system chime?
\t # Horizontal Tab
\v # Vertical Tab
\f # Formfeed
\n # Linefeed
\r # Carriage Return
\b # Backspace
\\ # Backslash. Prints a single backslash
\' \" # prints quotes
}}}
There are more than below, run '{{{help(os.path)}}}' to see the whole list:
{{{
import os
os.path.abspath # shorthand for {{{ normpath(join(os.getcwd(), path))}}}
os.path.basename # returns just the filename of a filepath
os.path.dirname # list just the directory component of a filepath
os.path.exists # returns bool whether a file or path exists
os.path.getsize # returns the KB size of a file
os.path.isdir # returns bool if the argument is a path
os.path.isfile # returns bool if the argument is a file
os.path.normcase # makes all text lowercase, and conforms the paths slashes to match your OS's standard.
os.path.normpath # conforms the paths slashes to match your OS's standard, removes extra slashes, relative paths.
os.path.split # split a pathname into (path, file)
os.path.splitdrive # split pathname into (drive, path)
os.path.splitext # split the pathname into (path, .extension)
os.path.walk # walk the directory tree and call functions
# also check out os.walk
}}}
Also this, to split a path into it's individual components, regardless of os:
{{{
import os
path = r"C:\temp\spam\eggs\file.txt"
split = os.path.normpath(path).split(os.sep)
}}}
/***
|''Name:''|LoadRemoteFileThroughProxy (previous LoadRemoteFileHijack)|
|''Description:''|When the TiddlyWiki file is located on the web (view over http) the content of [[SiteProxy]] tiddler is added in front of the file url. If [[SiteProxy]] does not exist "/proxy/" is added. |
|''Version:''|1.1.0|
|''Date:''|mar 17, 2007|
|''Source:''|http://tiddlywiki.bidix.info/#LoadRemoteFileHijack|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0|
***/
//{{{
version.extensions.LoadRemoteFileThroughProxy = {
major: 1, minor: 1, revision: 0,
date: new Date("mar 17, 2007"),
source: "http://tiddlywiki.bidix.info/#LoadRemoteFileThroughProxy"};
if (!window.bidix) window.bidix = {}; // bidix namespace
if (!bidix.core) bidix.core = {};
bidix.core.loadRemoteFile = loadRemoteFile;
loadRemoteFile = function(url,callback,params)
{
if ((document.location.toString().substr(0,4) == "http") && (url.substr(0,4) == "http")){
url = store.getTiddlerText("SiteProxy", "/proxy/") + url;
}
return bidix.core.loadRemoteFile(url,callback,params);
}
//}}}
Every so often, I'll get an [[exception|Understanding exceptions]] like this:
{{{
UnboundLocalError: local variable 'myVar' referenced before assignment
}}}
Here's a test case explaining the issue:
----
This this sample module {{{test.py}}}, there is a //global variable// named {{{shoe}}}. Inside the {{{main()}}} function, the function {{{stuff()}}} takes in the global variable and returns a new value. ''All is well:''
{{{
# test.py
# global var:
shoe = 23
def stuff(n):
return n * 2
def main():
# global var is passed into function:
var = stuff(shoe)
print var
if __name__ == "__main__":
main()
}}}
It prints
{{{
46
}}}
The below modification ''will fail:''
{{{
# test.py
shoe = 23
def stuff(n):
return n * 2
def main():
var = stuff(shoe)
print var
# note the assignment to shoe, making it *local*
shoe = 32
if __name__ == "__main__":
main()
}}}
When executed:
{{{
UnboundLocalError: local variable 'shoe' referenced before assignment
}}}
''What's going on?''
Python realizes that {{{shoe}}} has had an assignment made to it inside the {{{main()}}} function, thus making the declaration there //local to main()// ({{{main()}}} no longer pays any attention to the //global// {{{shoe}}}). And since this happened //after// {{{stuff()}}} consumed it, it appears to be an order of operation failure. A few solutions (trimming off the unmodified code):
!!!Pass in shoe:
{{{
# modify main as such:
def main(shoe=shoe):
}}}
!!!Put assignment //first//:
{{{
def main():
# made local first thing:
shoe = 32
}}}
!!!Make a function to explicitly modify the //global var//, and call to it:
{{{
def modShoe():
return shoe * 2
def main():
var = modShoe()
}}}
Found here: Found here: http://nodebox.net/code/index.php/Math
{{{
from math import radians, sin, cos
def coordinates(x0, y0, distance, angle):
x1 = x0 + cos(radians(angle)) * distance
y1 = y0 + sin(radians(angle)) * distance
return x1, y1
}}}
Python comes with a {{{logging}}} module:
http://docs.python.org/library/logging.html#logging.basicConfig
http://docs.python.org/howto/logging.html#logging-basic-tutorial
Simple Example:
https://docs.python.org/2.7/library/logging.html#logging.basicConfig
https://docs.python.org/3/library/logging.html#logging.basicConfig
Good deeper dive:
https://blog.urbanpiper.com/understanding-python-logging-library/
{{{
import logging
logging.basicConfig(filename="full path to the log file",level=logging.DEBUG,
format='%(asctime)s : %(levelname)s : %(message)s')
logging.debug('This message should go to the log file')
logging.info('So should this')
logging.warning('And this, too')
}}}
Example where two loggers are created, and updated independently
{{{
import logging
#-------------------------------
# Create the loggers:
# These names can be anything really, but must be different from
# what the logFiles are
loggerNames = ["mainLog", "errorLog"]
# Where to save the logs on disk. can also use leaf names to save
# in the same dir as this module:
logFiles = ['c:/temp/mainLog.log', 'c:/temp/errorLog.log']
# Collect the loggers we're about to create:
loggers = []
for i,theLogger in enumerate(loggerNames):
# Need to get a logger to run:
logger = logging.getLogger(theLogger)
loggers.append(logger)
# Set the level of logging that should be reported for this logger. This level and everything
# above it (worse) will be reported.
logger.setLevel(logging.DEBUG)
# Remove any handles that were made during previous executions, since logger
# is a singleton. Otherwise we'll get duplicate lines in our log.
for handler in logger.handlers:
logger.removeHandler(handler)
# Simple file handler:
fh = logging.FileHandler(logFiles[i])
# A more complex 'rotating file handler':
#fh = logging.handlers.RotatingFileHandler(logFiles[i], maxBytes=2000, backupCount=10)
# Optional: Set the level of logging for this *handler* that should be reported. This level and everything
# above it (worse) will be reported.
fh.setLevel(logging.DEBUG)
# Note the \r\n that needs to be entered to embed the newline:
formatter = logging.Formatter('%(asctime)s : %(levelname)s : %(message)s\r\n')
fh.setFormatter(formatter)
logger.addHandler(fh)
#---------------------------------------
# Now update the loggers independent from one another:
loggers[0].debug('MainLog: Debug logging message.')
loggers[0].info('MainLog: Info message.')
loggers[0].warning('MainLog: Warning message.')
loggers[0].error('MainLog: Error message.')
loggers[0].critical('MainLog: Critical error message.')
loggers[1].debug('Errorlog: Debug logging message.')
loggers[1].info('Errorlog: Info message.')
loggers[1].warning('Errorlog: Warning message.')
loggers[1].error('Errorlog: Error message.')
loggers[1].critical('Errorlog: Critical error message.')
#-------------------------------
# Finally, shutdown, so you can edit the files if need be:
logging.shutdown()
}}}
After executing, if you open mainLog.log:
{{{
2015-10-12 16:38:47,188 : DEBUG : MainLog: Debug logging message from Maya.
2015-10-12 16:38:47,190 : INFO : MainLog: Info message from Maya.
2015-10-12 16:38:47,190 : WARNING : MainLog: Warning message from Maya.
2015-10-12 16:38:47,190 : ERROR : MainLog: Error message from Maya.
2015-10-12 16:38:47,190 : CRITICAL : MainLog: Critical error message from Maya.
}}}
And errorLog.log:
{{{
2015-10-12 16:38:47,191 : DEBUG : Errorlog: Debug logging message from Maya.
2015-10-12 16:38:47,191 : INFO : Errorlog: Info message from Maya.
2015-10-12 16:38:47,191 : WARNING : Errorlog: Warning message from Maya.
2015-10-12 16:38:47,193 : ERROR : Errorlog: Error message from Maya.
2015-10-12 16:38:47,193 : CRITICAL : Errorlog: Critical error message from Maya.
}}}
See the Python reference here:
http://docs.python.org/tut/node7.html#SECTION007600000000000000000
Topics:
*Looping through dictionaries ({{{dict.iteritems}}}).
*Looping through a sequence, and having access to the current index and value ({{{enumerate}}}).
*Loop over two or more sequences at the same time ({{{zip}}}).
*Loop over a sequence in reverse ({{{reversed}}}).
*Loop over a sequence in sorted order ({{{sorted}}}).
Easier than just retyping it all ;)
----
Also see:
*[[How can I loop through multiple lists?]]
Python comes with the {{{math.sqrt}}} function, that calculates the.... square root of the value. But if what if you want different roots? Like the cube root? Or the quad root?
Two different solutions I [[found online|http://stackoverflow.com/questions/28014241/how-to-find-cube-root-using-python]]:
{{{
from math import pow
def getRoot(x, power):
return pow(x, (1. / power))
def getRoot(x, power):
return x ** (1. / power)
}}}
I ran a iterative test over both of them, and the 2nd {{{getRoot}}} (the one using the {{{**}}}) came in about 1.3x faster than the first one.
I'd done a test before comparing it's speeds here, and this backs it up: [[What's faster: pow, **, or mult]]
Examples:
{{{
#Square root of 4:
print getRoot(4, 2)
# 2.0
#Cube root of 27:
print getRoot(27, 3)
# 3.0
# Quad root of 27:
print getRoot(27,4)
# 2.27950705695
}}}
----
Also see:
* [[MATH : How can I test if a number is the power of 2?]]
Or really, the power of any number, but below, we use {{{2}}} :
{{{
import math
print math.log(4, 2).is_integer()
#True
print math.log(5, 2).is_integer()
#False
}}}
----
Also see:
* [[MATH : Calculate different roots]]
* https://www.kaggle.com/datasets
** Kaggle has it's own API, which is discussed here: https://github.com/Kaggle/kaggle-api
** For example, you can use this kaggle API (Python 3 based) command to do downloads:
*** {{{kaggle competitions download -c dog-breed-identification}}}
*** I'm told this also works in [[Google Collaboratory|Google Colaboratory : Overview]].
Pretty nice lib for dealing with magnetism:
* https://pypi.org/project/magpylib/
* https://magpylib.readthedocs.io/en/latest/
* https://magpylib.readthedocs.io/en/latest/_pages/2_guideExamples/
<<gradient horiz #ddddff #ffffff >>
[[Welcome]]
[[About wiki|About python tiddlywiki]]
[[Instructions for use]]
[[Latest Updates|History]]
[[Python Links]]
[[About author|WarpCat]]
[[Copyright Information|Copyright Information]]
----
''Subscribe'':
''[[RSS|http://pythonwiki.tiddlyspot.com/index.xml]]'' [img[http://farm1.static.flickr.com/197/492915948_b4a9f3233e.jpg?v=0][http://pythonwiki.tiddlyspot.com/index.xml]]
----
[[All Subjects]]
----
''Categories:''
[[AI]]
[[ALGORITHM]]
[[ANACONDA]]
[[ARDUINO]]
[[CIRCUITPYTHON]]
[[COLABORATORY]]
[[DATABASE]]
[[DICTIONARY]]
[[ENVIRONMENT]]
[[EXECUTION]]
[[EXTERNAL APPS]]
[[FILESYSTEMS]]
[[FUNDAMENTALS]]
[[INFO]]
[[I/O]]
[[JUPYTER]]
[[KIVY]]
[[LIST]]
[[MATH]]
[[MATPLOTLIB]]
[[MEDIA]]
[[NETWORK]]
[[NUMBERS]]
[[NUMPY]]
[[OOP]]
[[P4]]
[[PANDAS]]
[[PIL]]
[[PYGAME]]
[[PYSIDE]]
[[RASPBERRY PI]]
[[SCIPY]]
[[SET]]
[[STRING]]
[[TROUBLESHOOTING]]
[[UI]]
[[VARIABLES]]
[[VIRTUALENV]]
[[WEB]]
[[WING]]
[[XML]]
http://effbot.org/tkinterbook/bitmapimage.htm
From that page:
<<<
An X11 bitmap image consists of a C fragment that defines a width, a height, and a data array containing the bitmap. To embed a bitmap in a Python program, you can put it inside a triple-quoted string:
{{{
BITMAP = """
#define im_width 32
#define im_height 32
static char im_bits[] = {
0xaf,0x6d,0xeb,0xd6,0x55,0xdb,0xb6,0x2f,
0xaf,0xaa,0x6a,0x6d,0x55,0x7b,0xd7,0x1b,
0xad,0xd6,0xb5,0xae,0xad,0x55,0x6f,0x05,
0xad,0xba,0xab,0xd6,0xaa,0xd5,0x5f,0x93,
0xad,0x76,0x7d,0x67,0x5a,0xd5,0xd7,0xa3,
0xad,0xbd,0xfe,0xea,0x5a,0xab,0x69,0xb3,
0xad,0x55,0xde,0xd8,0x2e,0x2b,0xb5,0x6a,
0x69,0x4b,0x3f,0xb4,0x9e,0x92,0xb5,0xed,
0xd5,0xca,0x9c,0xb4,0x5a,0xa1,0x2a,0x6d,
0xad,0x6c,0x5f,0xda,0x2c,0x91,0xbb,0xf6,
0xad,0xaa,0x96,0xaa,0x5a,0xca,0x9d,0xfe,
0x2c,0xa5,0x2a,0xd3,0x9a,0x8a,0x4f,0xfd,
0x2c,0x25,0x4a,0x6b,0x4d,0x45,0x9f,0xba,
0x1a,0xaa,0x7a,0xb5,0xaa,0x44,0x6b,0x5b,
0x1a,0x55,0xfd,0x5e,0x4e,0xa2,0x6b,0x59,
0x9a,0xa4,0xde,0x4a,0x4a,0xd2,0xf5,0xaa
};
"""
}}}
To create X11 bitmaps, you can use the X11 bitmap editor provided with most Unix systems, or draw your image in some other drawing program and convert it to a bitmap using e.g. the [[Python Imaging Library|http://www.pythonware.com/products/pil/]].
<<<
^^Note: They list width and height to both be 32 in that example,but based on the values it would be 8x16. Not sure if that's a typo...^^
Those bits are stored as a hexadecimal string. If you turn the C im_bits array into a Python list and print, the string representation will be the integer value.
----
To do the conversion via PIL:
*http://www.pythonware.com/library/pil/handbook/image.htm
*Check out the {{{tobitmap()}}} function.
{{{
from PIL import Image
im = Image.open("myImage.jpg")
bitmap = im.tobitmap()
}}}
----
Here is a Python function that will create a X11 bitmap string from the given args.
{{{
def makeX11(width, height, bits):
"""
width : int : bitmap width.
height : int : bitmap height.
bits : list : List of int values. len(bits) must equal width * height.
"""
assert (width * height) == len(bits), "Width (%s) * height (%s) != len of bits (%s)"%(width, height, len(bits))
bitmapData = []
bitmapData.append("#define im_width %s"%width)
bitmapData.append("#define im_height %s"%height)
bitmapData.append("static char im_bits[] = {")
for h in range(height):
hexRow = [hex(bit) for bit in bits[h*width:h*width+width]]
bitmapData.append(', '.join(hexRow))
bitmapData.append("};")
return bitmapData
}}}
As an example, I converted the above hexadecimal values into ints:
{{{
width = 8
height = 16
bits = [175, 109, 235, 214, 85, 219, 182, 47,
175, 170, 106, 109, 85, 123, 215, 27,
173, 214, 181, 174, 173, 85, 111, 5,
173, 186, 171, 214, 170, 213, 95, 147,
173, 118, 125, 103, 90, 213, 215, 163,
173, 189, 254, 234, 90, 171, 105, 179,
173, 85, 222, 216, 46, 43, 181, 106,
105, 75, 63, 180, 158, 146, 181, 237,
213, 202, 156, 180, 90, 161, 42, 109,
173, 108, 95, 218, 44, 145, 187, 246,
173, 170, 150, 170, 90, 202, 157, 254,
44, 165, 42, 211, 154, 138, 79, 253,
44, 37, 74, 107, 77, 69, 159, 186,
26, 170, 122, 181, 170, 68, 107, 91,
26, 85, 253, 94, 78, 162, 107, 89,
154, 164, 222, 74, 74, 210, 245, 170]
bitmapData = makeX11(width, height, bits)
for bd in bitmapData:
print bd
}}}
prints the //exact// {{{BITMAP}}} string from above.
This is an easy way to make a new directory to store logs in, every time you call to the parental function:
{{{
import os
import datetime
DIR_LOG = "C:/temp/my_tool/logs"
def storeLog(data):
subLogDir= os.path.join(DIR_LOG , datetime.datetime.now().strftime("%Y%m%d-%H%M%S"))
os.makedirs(subLogDir)
# Which would make something like: C:/temp/my_tool/logs/20210711-210530
# Now write your data into that dir
# ...
}}}
Something nice the //Professional// version of Wing adds is access to it's own API. This means (among other things) you can write your own scripts to run //in Wing//. A practical example would be a new hotkey or ~RMB-menu item: I wanted a way to hilight a word in Wing, and pull up help on the topic. The Wing support crew was very quick in firing back this as a solution, which I've modified for my own uses:
{{{
# wingHotkeys.py
import urllib
import wingapi
def getWingText():
"""
Based on the Wing API, get the selected text, and return it
"""
editor = wingapi.gApplication.GetActiveEditor()
if editor is None:
return
doc = editor.GetDocument()
start, end = editor.GetSelection()
return doc.GetCharRange(start, end)
def googleSearch(site):
"""
Search the provided site for the highlighted text in Wing.
Parameters:
site : (str) The web site Google should search in (like 'docs.python.org')
"""
txt = getWingText()
url = urllib.urlencode((('q', txt + ' site:'+site), ('ie', 'utf-8')))
url = "http://www.google.com/search?" + url
wingapi.gApplication.OpenURL(url)
# Hotkey/menu commands to call to the search:
def pythonSearch():
googleSearch(txt, 'docs.python.org')
def pySideSearch():
googleSearch(txt, 'srinikom.github.io/pyside-docs/')
}}}
This is saved here (inside Wing's 'Settings Directory' found via the Help->About... menu):
{{{
C:\Users\<userName>\AppData\Roaming\Wing IDE 5\scripts\wingHotkeys.py
}}}
I found that you can't pass args into hokeys via Wings hotkey editor, so I made master function ({{{googleSearch()}}}) that does the work, and then I make unique hotkey functions ({{{pythonSearch()}}} & {{{pySideSearch()}}}) that I map to specific hotkeys/menus, based on the type of search I want.
Once your commads are setup, you can map them to hokeys via:
*Edit -> Preferences -> Keyboard -> Custom Key Bindings
Or you can add them to Wing's ~RMB-menu via either:
*~RMB-menu -> Configure Menu...
*Edit -> Preferences -> Editor -> Context Menu
Then "Insert" them in the "Custom Items" section.
''NOTE''
>Wing itself runs a different version of Python than you may have installed. This is only really important if you get the "Pro" version, and start making your own 'plugin scripts': The plugins you author will be running Wings version of Python, not your installed version of Python. Furthermore, the Wing distribution isn't the full install of Python, so not all modules are available. This isn't a huge deal, but it's important to be aware of if your plugins don't work. For example, I had one that called to the {{{webbrowser}}} module: That module isn't distributed with Wing. Luckily, they have their own function ({{{wingapi.gApplication.OpenURL(url)}}}) that could be used in its place.
API Docs:
*http://www.wingware.com/doc/scripting/api
*http://www.wingware.com/doc/commands/index
The wingapi.py file is found here:
{{{
C:\Program Files (x86)\Wing IDE 5.0\bin\wingapi.py
}}}
*http://www.doughellmann.com/PyMOTW/math/
**Great overview of the {{{math}}} module in the standard library
*http://inventwithpython.com/blog/2012/07/18/using-trigonometry-to-animate-bounces-draw-clocks-and-point-cannons-at-a-target/
**Great visual overview for using trigonometry to animate stuff using Pygame.
*[[Autodesk University: ICE Design Tools|http://area.autodesk.com/userdata/blogs/marks/ToddAkita_ICE_Design_Tools.pdf]] (pdf) - This is for Softimage's ICE, but the reference it has for trig and vectors is great.
I recently found [[these sites:
*http://webdesign.about.com/od/localization/l/blhtmlcodes-math.htm
*http://ancienthistory.about.com/od/greeklanguage/a/ASCIIGreek.htm
that gives me the ascii codes so I can embed them in the wiki... so let's get started...
----
!!!Delta (upper case)
∆ [[Change|http://en.wikipedia.org/wiki/Delta_(letter)#Upper_case]]
!!!Delta (lower case)
δ
!!!Sigma (upper-case)
∑ [[Summation|http://en.wikipedia.org/wiki/Summation]]
[img[http://upload.wikimedia.org/math/f/b/8/fb801f888eb8feb345c585023293d44f.png]] {{{sum(range(1,101))}}} = 5050
[img[http://upload.wikimedia.org/math/1/a/6/1a693bfe9a392b08ed135a9e4117d3b9.png]] {{{sum([i**2 for i in range(3,7)])}}}
!!!Sigma (lower-case)
σ
Docs:
* Main: https://matplotlib.org/3.3.3/contents.html
* Examples: https://matplotlib.org/3.3.3/gallery/index.html
* Tutorials: https://matplotlib.org/3.3.3/tutorials/index.html
* Style sheet reference: https://matplotlib.org/3.1.1/gallery/style_sheets/style_sheets_reference.html
* Common classes:
** https://matplotlib.org/3.3.3/api/_as_gen/matplotlib.pyplot.html
** https://matplotlib.org/3.3.3/api/_as_gen/matplotlib.figure.Figure.html
** https://matplotlib.org/3.3.3/api/axes_api.html
* Cheat Sheets
** https://www.datacamp.com/community/blog/python-matplotlib-cheat-sheet
! Anatomy of a Matplotlib plot
* Figure : Highest level thing, think of it as the frame or window. This can have a title.
** Axes : These are the 'sub-plots' that visualize the data. There is always one, but can have multiple, in rows / columns. These can have titles, x/y lables, and legends
! OO Example
There's two ways to interact with the data: The ~Object-Oriented way, and the ~PyPlot way:
https://matplotlib.org/3.3.3/tutorials/introductory/lifecycle.html
High level: Generally use the OO method vis the 'state-based' ~PyPlot way.
Common way/namespace to import. Also, matplotlib, pandas, and numpy all use the numpy array backend, and data is easily interchangeable:
{{{
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
}}}
Make two subplots (axes) in a figure, each displaying differnt data:
{{{
# Read some medical data, via Pandas:
heart_disease = pd.read_csv("heart-disease.csv")
# create a new dataset, by filtering the existing one by any age over 50:
over_50 = heart_disease[heart_disease["age"] > 50]
# Set a visual style to use:
plt.style.use('seaborn-whitegrid')
# Create our high-level 'figure', and two axes (subplots)
fig, (ax0, ax1) = plt.subplots(nrows=2, # Each 'row' in this case represents an axis.
ncols=1,
figsize=(10,10),
sharex=True) # Share the x-axis labels
# Add a title to the whole figure:
fig.suptitle("Heart Disease Analysis", fontsize=16, fontweight="bold"); # suptitle = 'super title'?
# Add data at ax0 as a scatterplot:
scatter0 = ax0.scatter(x=over_50["age"],
y=over_50["chol"],
c=over_50["target"],
cmap="winter") # adjust colors!
# Customize ax0
ax0.set(title="Heart Disease and Cholesterol Levels",
# xlabel="Age", # are sharing, don't need to put here
ylabel="Cholesterol")
# Set the x-axis limits
ax0.set_xlim([50,80])
# Add a legend to ax0:
ax0.legend(*scatter0.legend_elements(), title="Target")
# Add a meanline
ax0.axhline(y=over_50["chol"].mean(),
linestyle="--")
#--- Now do ax1
# Add data ot ax1:
scatter1 = ax1.scatter(x=over_50["age"],
y=over_50["thalach"],
c=over_50["target"],
cmap="winter") # adjust colors!
# Customize ax1
ax1.set(title="Heart Disease and Max Heart Rate (Thalach)",
xlabel="Age", # Our shared label
ylabel="Max Heart Rate (Thalach)")
# Set the x-axis limits -------------------
ax1.set_xlim([50,80])
ax1.set_ylim([60,200])
# Add a legend to ax1:
ax1.legend(*scatter1.legend_elements(), title="Target")
# Add a meanline
ax1.axhline(y=over_50["thalach"].mean(),
linestyle="--")
# Save the figure out, at the exact resolution it's shown at above
fig.savefig("heart-disease-ayalysis-plot-saved-with-code.png")
}}}
You can also use state-based 'styles' to change the look:
{{{
# https://matplotlib.org/3.1.1/gallery/style_sheets/style_sheets_reference.html
print(plt.style.available)
# Everything after this will use this style
plt.style.use('seaborn-whitegrid')
}}}
http://matplotlib.org/
https://github.com/matplotlib/matplotlib/downloads
The bulk of these notes are pulled from [[Programming Computer Vision With Python|http://shop.oreilly.com/product/0636920022923.do]]
The ~PyLab interface is the set of functions that allow the user to create plots. {{{pylab}}} is actually a module in the {{{matplotlib}}} package ({{{matplotlib.pylab}}}), however, it also gets its own module external to that packaged that lives at the root of the site-packages dir you can import directly. It only has three lines:
{{{
# Never 'import *', made these notes a long time ago:
from matplotlib.pylab import *
import matplotlib.pylab
__doc__ = matplotlib.pylab.__doc__
}}}
Matplotlib can use PIL Image objects directly, the below examples make use of them.
It should also be noted that the ~PyLab {{{array}}} type is actually borrowed from Numpy.
----
For the below examples:
{{{
from PIL import Image
from pylab import *
}}}
----
Plot an image:
The {{{show()}}} command starts the figure GUI and raises the figure windows. Call {{{show()}}} only once per script, usually at the end.
{{{
im = array(Image.open('spam.jpg'))
imshow(im)
show()
}}}
----
Don't use colors:
{{{
gray()
}}}
----
Create a new window (figure):
{{{
figure()
}}}
Calling this to multiple times in a module will set this as the active window, and display it when {{{show()}}} is called.
----
Turn off axes:
{{{
axis('off')
}}}
----
Plot lines and points:
{{{
plot(x,y,'color & style')
}}}
'Color & style is a special string combos that are combined:
*Colors : 'r' = red, 'g' = green, 'b' = blue, 'c' = cyan, 'm' = magenta, 'y' = yellow, 'k' = black, 'w' = white.
*Styles : ' - ' : solid, ' - - ' : dashed, ' : ' : dotted.
*Marker : ' . ' : point, ' o ' : circle, ' s ' : square, ' * ' : star, ' + ' : plus, ' x ' : x.
Examples:
*'r*' : red star markers.
*'go-' : green line with circle markers.
*'ks:' : black dotten line with square markers.
----
Display a histogram for an image:
{{{
# Open an image, convert to gray-scale:
im = array(Image.open('spam.jpg').convert('L'))
figure()
gray()
hist(im.flatten(), 128)
show()
}}}
----
Display image contours (edge-detection):
{{{
# Open an image, convert to gray-scale:
im = array(Image.open('spam.jpg').convert('L'))
figure()
gray()
contour(im, origin='image')
show()
}}}
----
Get three interactively-picked points
{{{
points = ginput(3)
}}}
The user can then pick three points in the current image, points will be a list of tuples of two (x,y) values.
----
! Working with images
{{{
from matplotlib.image import imread
panda = imread("panda.png")
type(panda)
# numpy.ndarray # <--- ooooohhh
}}}
Thought I'd try my hand at a maze solver. It works, but doesn't tell you the path it took, just that it solved it. It's.. a start ;)
{{{
maze =\
"""
.X..X.
.XX...
....XX
XXX...
X...X.
O.XX..
"""
# This creates entries in y,x order:
mazer = [list(row) for row in maze.split()]
def check(position):
if position[0] < 0 or position[1] < 0:
return False
try:
val = mazer[position[0]][position[1]]
except IndexError:
return False
if val == 'O':
return "cheese"
elif val == 'X':
return False
else:
return True
def solve(maze, start = [0,0]):
"""
maze : string : Any multiline string. Empty spaces are marked with period '.'.
Walls are marked with capital X. The exit is marked with capital O.
start : The x,y] location to start the maze at.
return : The x,y coordinate of the exit, or False if the puzzle can't be solved.
"""
# flip to y,x for internal processing.
start = [start[1], start[0]]
north,south,east,west = [-1,0], [1,0], [0,1], [0,-1]
cheese = False
visited = []
positions = [start]
for p in positions:
if cheese:
break
visited.append(p)
for direction in [north,south,east,west]:
location = [p[0]+direction[0], p[1]+direction[1]]
if location in visited:
continue
result = check(location)
if result == 'cheese':
cheese = location
elif result:
positions.append(location)
# Flip y,x to x,y:
return cheese[1], cheese[0]
print solve(maze)
}}}
{{{
(0, 5)
}}}
Methods are [[Function]]s that are called using the [[attribute]] notation. There are two flavors: built-in methods (such as .append() on lists) and class instance methods. Built-in methods are described with the types that support them. You can create methods in your [[Class]] objects.
When you inherit a class and it's method, it's possible to additionally either override an inherited method, or modify an inherited method. To //override// a method, you simply redefine the method in your new derived class. But to modify an inherited method, you need to use the {{{super}}} function. Based on the [[Class Inheritance]] example:
{{{
# make a new derived class, that modifies Foo's __init__ method (now accepts 'newVal') without overriding it:
class Fooie(Foo):
def __init__(self, val, newVal):
super(Fooie, self).__init__(val)
self.newVal = newVal
}}}
{{{super}}} lets you invoke the method of a base class (also called a //superclass//), and pass its values to the derived class. So in th above example, {{{super}}} is getting the {{{val}}} data from the 'base class'\superclass {{{Foo}}}, and assigning it to the derived class {{{Fooie}}}'s inherited {{{val}}} attribute. {{{super}}} was introduced in Python 2.2, and only works with 'new style classes': Meaning, classes defined as {{{class Foo(object):}}} rather than {{{class Foo:}}}.
I wanted a good way to understand how Python's 'method resolution order' worked, so I made the below example.
In it, we have a primary superclass ({{{Super}}}) that defines two methods to execute ({{{method1}}}, {{{method2}}}), plus one called {{{build}}} that executes them in order.
Then, I create two subclasses of {{{Super}}} ({{{BB}}}, and {{{CC}}}), that both implement their own versions of {{{method1}}} and {{{method2}}}, but as adds, not overrides, to those in the superclass. A bunch of printing later, and you get the results.
The takeaway: It executes subclasses in reverse order. Since I want {{{BB}}} to execute before {{{CC}}}, I must define the class that inherits from them as such:
{{{
class DD(CC, BB): # reverse order of execution.
}}}
So, here is the example code:
{{{
class Super(object):
"""
The Superclass that others will inherit from. It defines the methods that
all others will share, and has the build method that calls to them all in
the correct order.
"""
def __init__(self):
print("In Super.__init__")
print ("Doing Super.__init__ stuff")
self.dataI = ["Si"]
self.data1 = []
self.data2 = []
def method1(self):
print("In Super.method1")
print("Doing Super.method1 stuff")
self.data1.append("S1")
def method2(self):
print("In Super.method2")
print("Doing Super.method2 stuff")
self.data2.append("S2")
def build(self):
"""
Run the methods in a given order.
"""
print("Starting Super.build")
for method in [self.method1, self.method2]:
method()
print("Ending Super.build")
class BB(Super):
def __init__(self):
print("In BB.__init__")
print ("Calling to Super.__init__")
super(BB, self).__init__()
print ("Doing BB.__init__ stuff")
self.dataI.append("BBi")
def method1(self):
print("In BB.method1")
print ("Calling to Super.method1")
super(BB, self).method1()
print ("Doing BB.method1 stuff")
self.data1.append("BB1")
def method2(self):
print("In BB.method2")
print ("Calling to Super.method2")
super(BB, self).method2()
print ("Doing BB.method2 stuff")
self.data2.append("BB2")
class CC(Super):
def __init__(self):
print("In CC.__init__")
print ("Calling to Super.__init__")
super(CC, self).__init__()
print ("Doing CC.__init__ stuff")
self.dataI.append("CCi")
def method1(self):
print("In CC.method1")
print ("Calling to Super.method1")
super(CC, self).method1()
print ("Doing CC.method1 stuff")
self.data1.append("CC1")
def method2(self):
print("In CC.method2")
print ("Calling to Super.method2")
super(CC, self).method2()
print ("Doing CC.method2 stuff")
self.data2.append("CC2")
class DD(CC, BB):
"""
A class that implements both BB & CC, which are both based on Super.
"""
def __init__(self):
print("In DD.__init__")
print("Calling to multiple superclasss __init__'s:")
super(DD, self).__init__()
print("--- Creating DD Class Instance ---")
dd = DD()
print("--- DD Instancing over---")
print ("Calling to DD.build")
dd.build()
print("dd datai", dd.dataI)
print("dd data1", dd.data1)
print("dd data2", dd.data2)
}}}
And the output printing is:
{{{
--- Creating DD Class Instance ---
In DD.__init__
Calling to multiple superclasss __init__'s
In CC.__init__
Calling to Super.__init__
In BB.__init__
Calling to Super.__init__
In Super.__init__
Doing Super.__init__ stuff
Doing BB.__init__ stuff
Doing CC.__init__ stuff
--- DD Instancing over---
Calling to DD.build
Starting Super.build
In CC.method1
Calling to Super.method1
In BB.method1
Calling to Super.method1
In Super.method1
Doing Super.method1 stuff
Doing BB.method1 stuff
Doing CC.method1 stuff
In CC.method2
Calling to Super.method2
In BB.method2
Calling to Super.method2
In Super.method2
Doing Super.method2 stuff
Doing BB.method2 stuff
Doing CC.method2 stuff
Ending Super.build
('dd datai', ['Si', 'BBi', 'CCi'])
('dd data1', ['S1', 'BB1', 'CC1'])
('dd data2', ['S2', 'BB2', 'CC2'])
}}}
Interesting Things:
* Even though the {{{Super.__init__}}} is called to multiple times, it only executes once.
* By listing the superclasses in reverse order when defining {{{DD}}}, they execute in the correct order.
* All the data is listed correctly, in the right order.
Blog post showing how to use {{{PyWin32}}} to monkey with Microsoft Office:
http://www.blog.pythonlibrary.org/2010/07/16/python-and-microsoft-office-using-pywin32/
This example shows how to add a method to an instance of a class: Only that one instance will have it:
{{{
import types
class Spam(object):
pass
spam = Spam()
def monkeyMeth(self, value):
"""
Some new method
"""
return value * 10
spam.monkeyMeth = types.MethodType( monkeyMeth, spam )
print spam.monkeyMeth(3)
# 30
}}}
----
Also see:
*[[How can I override an instance method?]]
So it is known you can make multiline strings like so:
{{{
s = """
lineA
lineB
lineC
"""
}}}
However, this will cause an extra line to be printed before, and after the multi-line block:
{{{
print "above"
print s
print "below"
}}}
{{{
above
lineA
lineB
lineC
below
}}}
To get around this, you can use a line escape characters to the mix:
{{{
s = """\
lineA
lineB
lineC\
"""
print "above"
print s
print "below"
}}}
{{{
above
lineA
lineB
lineC
below
}}}
''Mutable'' objects can be changed in-place (usually via their [[Method]]s). ''Immutable'' objects can't. Here's //the list// (hope I got it right...):
*''Mutable''
**list
**dictionary
*''Immutable''
**tupple
**string
**numbers (int, long, bool, float, complex, set, decima, etc...)
See Python docs on [[Mutable Sequence Types|http://docs.python.org/lib/typesseq-mutable.html]]
The [[PEP 8 Style Guide|http://python.org/dev/peps/pep-0008/]], under ' {{{Prescriptive: Naming Conventions}}} ' (search for it on that page) has many good naming conventions. No point to retype it all here, go there to see what's going on. But, here's a handy chart:
| Name Type | only lowercase | mixedCase | only uppercase | underscores (inside the name) | notes | example |
| | | | | | | |
| [[package|Packages]] | X | | | discouraged | short names | {{{spam}}} |
| [[module]] | X | | | if it improves readability | short names | {{{spam}}} \ {{{spam_eggs}}} |
| [[class|Class]] | | X | | | Classes always //start capitalized// (using the ~CapWords\~CamelCase convention) | {{{Spam}}} \ {{{SpamEggs}}} |
| [[function|Function]] or [[method|Class Methods]] | should be | only if it's the prevailing style | | as necessary to improve readability | | {{{spam}}} \ {{{spam_eggs}}} \ {{{spamEggs}}} |
| global variable | should be | only if it's the prevailing style | | as necessary to improve readability | | {{{spam}}} \ {{{spam_eggs}}} \ {{{spamEggs}}} |
| constants | | | X | X | | {{{SPAM}}} \ {{{SPAM_EGGS}}} |
Many of these can be modified with 'special underscores', please see the section below:
!Underscores
Per the //Naming Convention// section of the [[PEP8 Style Guide|http://www.python.org/dev/peps/pep-0008/]] under ' {{{Descriptive: Naming Styles
}}} '
*{{{_single_leading_underscore}}}
**weak "internal use" indicator. E.g. "{{{from M import *}}}" does not import objects whose name starts with an underscore.
*{{{single_trailing_underscore_}}}
**used by convention to avoid conflicts with Python keyword, e.g. {{{Tkinter.Toplevel(master, class_='ClassName')}}}
*{{{__double_leading_underscore}}}
**when naming a [[class|Class]] attribute, invokes name mangling (inside {{{class FooBar}}}, {{{__boo}}} becomes {{{_FooBar__boo}}}). See [[Private Attributes]] & [[Private Methods]]
*{{{__double_leading_and_trailing_underscore__}}}
**"magic" objects or [[attribute]]s that live in user-controlled namespaces. E.g. {{{__init__}}}, {{{__import__}}} or {{{__file__}}}. Never invent such names; only use them as documented. See [[Special Methods]], [[Special Attributes]]
!'Dots' in names:
This was sort of a 'oh, durrr...' moment on my part:
Don't name anything in Python with a 'dot\period' in their names: Modules, functions, classes, attributes.... anything. Python will raise a {{{SyntaxError}}}. This is because the 'dot' refers to an [[attribute]], not some sub-part of the name.
This may seem fairly obvious, but I had named a module, and the dir it was in like such, to track versioning:
{{{
c:\pyStuff\proj.0.2.1\proj.0.2.1.py
}}}
//Executing// the code from the command-line\icon worked just fine. But if you try to import that into another module, it just won't work. To make it work if you really want to use the versioning, use underscores:
{{{
c:\pyStuff\proj_0_2_1\proj_0_2_1.py
}}}
Live and learn ;)
Standard deviation and variances are the measures of the spread of data.
{{{
import numpy as np
high_var_array = np.array([1,100,200, 300, 4000,5000]) # more sperad out
low_var_array = np.array([2,4,6,8,10]) # closer together
}}}
mean : The average of something:
{{{
np.mean(high_var_array), np.mean(low_var_array)
(1600.1666666666667, 6.0)
}}}
variance : the measure of the average degree to which each number is different to the mean.
higher variance = wider range of number
lower variance = lower range of numbers.
{{{
np.var(high_var_array), np.var(low_var_array)
(4296133.472222221, 8.0)
}}}
Standard deviation is a measure of how spread-out a group of numbers is from mean.
So, any number in high-var is on average 2072 away from the mean (1600) and any number in low-var is on average 2.8 away from the mean (6)
{{{
np.std(high_var_array), np.std(low_var_array)
(2072.711623024829, 2.8284271247461903)
}}}
Plot it: The y axis shows how many numbers appear near that value
{{{
import matplotlib.pyplot as plt
plt.hist(high_var_array)
plt.show()
plt.hist(low_var_array)
plt.show()
}}}
A lot of these notes are pulled from [[Programming Computer Vision With Python|http://shop.oreilly.com/product/0636920022923.do]]
----
!Docs, etc:
http://numpy.scipy.org/
http://docs.scipy.org/doc/numpy/reference/
https://numpy.org/doc/stable/user/basics.broadcasting.html <-- pretty important to understand how arrays work in relationship to each other
! Tutorials
* Python ~NumPy For Your Grandma
** https://www.gormanalysis.com/blog/python-numpy-for-your-grandma-1-1-introduction/
** https://www.reddit.com/r/Python/comments/l1jdcj/i_made_a_course_on_numpy_it_got_good_reviews_but/
** https://www.youtube.com/playlist?list=PL9oKUrtC4VP6gDp1Vq3BzfViO0TWgR0vR
* https://towardsdatascience.com/10-quick-numpy-tricks-that-will-make-life-easier-for-a-data-scientist-35a0253c7479
Cheat Sheets:
* https://www.datacamp.com/community/blog/python-numpy-cheat-sheet
----
!Numpy Arrays:
http://docs.scipy.org/doc/numpy/reference/arrays.html
Great visual overview:
https://academy.zerotomastery.io/courses/700485/lectures/14123223
{{{
# Example opening a PIL Image into an array:
from PIL import Image
from numpy import array
im = array(Image.open(myImage))
}}}
*Multi-dimensional, can represent vectors, matrices, and images.
*Can perform matrix multiplication, transposition, vector math.
*Array's are like lists of lists, but is restricted to having all elements of the same type.
It should be noted that both Panda's ~DataFrame, Matlotlib's {{{pylab}}} interface, and PIL's Images all use {{{array}}} types on the backend.
!!{{{ndarray}}} Attribues:
*{{{shape}}}
** (3) : (columns), (axis2) - Vector - {{{ndim}}} = 1
** (3,3) : (rows, columns), (axis1, axis2) - Matrix {{{ndim}}} = 2
** (2,3,3) : (dimensions, rows, columns), (axis0, axis1, axis2) - nDimensional Matrix {{{ndim}}} = 3
** //However//, they can have as many dimensions as possible. For example, {{{(2,3,4,5)}}}:
*** 2 'primary dimensions, 3 'sub dimensions', 4 columns, 5 rows.
*** Or you could think of it as, two 3d spaces who's 3d sizes are 3x4x5.
*** But since this can be any number of dimensions, it can get pretty complex, and hard to visualize after a while: {{{(4,5,6,7,8,9)}}}
*{{{dtype}}} : The data type of the array elements. Images are usually encoded with unsigned 8-bit integers ({{{uint8}}}). Grayscale images are {{{float32}}}. If there are different number types in an array, it will return the 'most complex' type.
* {{{ndim}}} : The number of dimensions to the array
* {{{size}}} the total number of elements in the array.
!! Reshape Arrays
* To multiply arrays (for example), they must have the same shape.
* If you know 'array2' is a shape of (2,3,3), and 'array1' has a shape of (2,3), you can reshape array2 to fit:
* {{{a2_reshape = array2.reshape(2,3,1)}}}
* Not the last element isn't a '3', it's a '1': This is ok for multiplication.
!! Transpose Arrays
* Transposing changes the shape: If it was (3,2), it becomes (2,3)
* {{{a2_transposed = a2.T}}}
!! Array comparison
https://numpy.org/doc/stable/reference/routines.logic.html
All the standard python operators apply.
The result returns a new array telling us the comparison of the element in a1 vs a2:
{{{
a1 = array([1, 2, 3])
a2 = array([[1. , 2. , 3.3],
[4. , 5. , 6.5]])
a1 > a2
array([[False, False, False],
[False, False, False]])
a1 == a2
array([[ True, True, False],
[False, False, False]])
}}}
!! Array multiplication
Two ways:
Element-wise does a direct multiply of each corresponding index in each array to make a new one.
The shapes must be the same.
{{{
a3 = a1 * a2
}}}
Dot Product works on matrices of different shapes, but there are some rules:
* When comparing sizes, say (5,3) & (5,3) the numbers on the 'inside' (aka, either side of the '&') must match.
* If the inside numbers aren't the same, it's possible to transpose the array to make them so:
{{{
mtx1.shape, mtx2.shape
# (5,3), (5,3)
# Transpose mtx2 to be (3,5), so the shapes are (5,3), (3,5) : Insides match.
mtx3 = np.dot(mtx1, mtx2.T)
}}}
!! Sorting arrays
{{{
random_array = np.random.randint(10, size=(3,5))
array([[8, 6, 6, 8, 6],
[3, 8, 2, 5, 2],
[9, 0, 1, 9, 5]])
# Sort by values:
np.sort(random_array)
array([[6, 6, 6, 8, 8],
[2, 2, 3, 5, 8],
[0, 1, 5, 9, 9]])
# Sort by indices:
np.argsort(random_array)
array([[1, 2, 4, 0, 3],
[2, 4, 0, 3, 1],
[1, 2, 4, 0, 3]], dtype=int64)
}}}
Sort by column. See [[here|https://stackoverflow.com/questions/2828059/sorting-arrays-in-numpy-by-column]]
{{{
distances = np.array([.2, .5, .7, .1])
indexes = np.array([0, 1, 2, 3])
combined = np.column_stack( [distances,indexes] )
print(combined)
# Sort the combined array using the first column of each
srt = combined[ combined[:,0].argsort() ]
print(srt)
[[0.2 0. ]
[0.5 1. ]
[0.7 2. ]
[0.1 3. ]]
[[0.1 3. ]
[0.2 0. ]
[0.5 1. ]
[0.7 2. ]]
}}}
!! Get min/max values:
{{{
a1 = np.array([1,2,3])
np.argmin(a1)
0 # index 0 is the min value
np.argmax(a1)
2 # index 2 is the max value
}}}
If using on a 2d array, you can provide axis=0 (array of max indices per column) or axis=1 (array of max indices per row).
!!Element Access:
Via indices.
{{{
Get the value at coord x,y (row, column), color c:
value = im[x,y,c]
}}}
Arrays support full slicing support, with querying and assignment.
!Image operations:
!! Via Matplotlib
{{{
from matplotlib.image import imread
myImage = imread("images/panda.png")
type(myImage )
# numpy.ndarray
myImage.shape
# So this is interesting: It's saying (based on how numpy arrays work, based on the number of channels they have):
# 2330 dimensions, 3500 rows, 3 columns
# but we know this is really x(columns)3500, y(rows)2330) z(dimension) 3
# (2330, 3500, 3)
}}}
!! Via PIL
{{{
# Open image, convert to grayscale, stick in array:
im = np.array(Image.open(myImage).convert('L'))
}}}
Invert an image:
{{{
inverted = 255 - im
}}}
Clamp intensities to between values 100->200
{{{
clamp = (100.0/255) * im + 100
}}}
Apply a quadratic function lowering the values of the darker pixels:
{{{
quad = 255.0 * (im/255.0)**2
}}}
Print the min and max values:
{{{
print int(im.min()), int(im.max())
}}}
Convert an array back to a PIL Image type:
{{{
pil_im = Image.fromarray(im)
#If the image was changed to a different format:
from numpy import uint8
pil_im = Image.fromarray(uint8(im))
}}}
!! Random Array Creation:
{{{
random_array = np.random.randint(0,10, size=(3,5))
# array([[9, 9, 5, 7, 9],
# [7, 8, 0, 9, 5],
# [1, 4, 4, 9, 9]])
random_array_2 = np.random.random((5,3))
# array([[0.65001797, 0.77695486, 0.86644714],
# [0.20784713, 0.73141035, 0.4824566 ],
# [0.78310267, 0.52190477, 0.89123055],
# [0.17027377, 0.10056597, 0.66061952],
# [0.6816164 , 0.53631945, 0.77977045]])
random_array_3 = np.random.rand(5,3)
# array([[0.10839724, 0.55202307, 0.80064482],
# [0.36884771, 0.95792632, 0.79720087],
# [0.71416286, 0.92939968, 0.83825807],
# [0.32372676, 0.63573224, 0.09355106],
# [0.53642133, 0.34368753, 0.41630812]])
}}}
!! Creating arrays with pre-defined numbers:
{{{
ones = np.ones((2,3))
zeros = np.zeros((2,3))
range_array = np.arange(0,10,2)
# array([0, 2, 4, 6, 8])
linear_distribution = np.linspace(0,10,10)
#array([ 0.0 , 1.11111111, 2.22222222, 3.33333333, 4.44444444,
# 5.55555556, 6.66666667, 7.77777778, 8.88888889, 10.0 ])
}}}
!! Working with random numbers:
{{{
# This will set the seed for all function calls after it, so the random
# numbers produced will be the same each time
np.random.seed(seed=0)
}}}
!! Others:
{{{
# Find unique numbers in an array:
random_array_4 = np.random.randint(10, size=(5,3))
array([[5, 0, 3],
[3, 7, 9],
[3, 5, 2],
[4, 7, 6],
[8, 8, 1]])
np.unique(random_array_4 )
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
}}}
! using Numpy's array math functions
{{{sum}}} {{{min}}} {{{max}}} {{{std}}} {{{var}}} {{{mean}}}
{{{
# this is always faster:
np.sum(myArray)
# than this:
sum(myArray)
# Since it uses NumPy's C code, not the Python code to do the sum.
# Examples have shown it being up to 170x faster, or Python .0006 slower.
}}}
----
Also see:
* [[NumPy : Standard Deviation and Variance]]
Nice overview on [[effbot.org|http://effbot.org/zone/python-objects.htm]]
----
All objects have three main data-points that describe them:
*identity: Its location in memory, accessed via {{{id()}}}.
*type: The representation of the object to Python, accessed via {{{type()}}}.
*value: The data (attributes) stored inside, accessed via {{{dir()}}}.
{{{
# Make a 'string' object assigned to the 'spam' variable:
spam = "eggs"
print "spam id:", id(spam)
print "spam type:", type(spam)
print "spam attributes:"
for d in dir(spam):
print "\t",d
}}}
Prints:
{{{
spam id: 50854480
spam type: <type 'str'>
spam attributes:
__add__
__class__
__contains__
__delattr__
#... many, many more....
}}}
http://www.open3d.org/
!Install
pip
{{{
pip install open3d
}}}
https://anaconda.org/open3d-admin/open3d
{{{
conda install -c open3d-admin open3d
}}}
! Import/Export formats
Per http://www.open3d.org/docs/release/tutorial/geometry/file_io.html
* Import Point Cloud Formats: [[xyz|https://en.wikipedia.org/wiki/XYZ_file_format]], xyzn, xyzrgb, pts, [[ply|http://paulbourke.net/dataformats/ply/]], [[pcd|http://pointclouds.org/documentation/tutorials/pcd_file_format.html]]
* Export Mesh Formats: [[ply|http://paulbourke.net/dataformats/ply/]], [[stl|http://www.fabbers.com/tech/STL_Format]], [[obj|http://paulbourke.net/dataformats/obj/]], [[off|http://www.geomview.org/docs/html/OFF.html]], [[gltf/glb|https://github.com/KhronosGroup/glTF/tree/master/specification/2.0]]
! Example
Combination from:
* http://www.open3d.org/docs/release/tutorial/geometry/surface_reconstruction.html
* https://towardsdatascience.com/5-step-guide-to-generate-3d-meshes-from-point-clouds-with-python-36bad397d8ba
Copy an example file from [[HERE|https://drive.google.com/drive/folders/1Ih_Zz9a6UcbUlaA-puEB_is7DYvXrb4w]] into dir, like below.
Note, they don't all seem to work with {{{np.loadtxt}}}, but the {{{.xyz}}} do.
{{{
import numpy as np
import open3d as o3d
input_file = r"C:\temp\reconstruct\sample.xyz"
output_path = r"C:\temp\reconstruct"
#-----------------------------------
# Read file, setup initial values:
#----
# Method A : Using numpy to populate the PointCloud data directly:
point_cloud = np.loadtxt(input_file, skiprows=1)
pcd = o3d.geometry.PointCloud()
pcd.points = o3d.utility.Vector3dVector(point_cloud[:,:3])
try:
pcd.colors = o3d.utility.Vector3dVector(point_cloud[:,3:6]/255)
except:
pass
try:
pcd.normals = o3d.utility.Vector3dVector(point_cloud[:,6:9])
except:
pcd.estimate_normals()
#----
# Method B using:
# http://www.open3d.org/docs/release/tutorial/geometry/file_io.html
pcd = o3d.io.read_point_cloud(input_file)
pcd.estimate_normals()
# Preview the cloud (optional)
# o3d.visualization.draw_geometries([pcd])
#-----------------------------------
# Ball-Pivoting Algorithm
distances = pcd.compute_nearest_neighbor_distance()
avg_dist = np.mean(distances)
radius = 3 * avg_dist
# Generate Mesh
bpa_mesh = o3d.geometry.TriangleMesh.create_from_point_cloud_ball_pivoting(pcd, o3d.utility.DoubleVector([radius, radius * 2]))
dec_mesh = bpa_mesh.simplify_quadric_decimation(100000)
dec_mesh.remove_degenerate_triangles()
dec_mesh.remove_duplicated_triangles()
dec_mesh.remove_duplicated_vertices()
dec_mesh.remove_non_manifold_edges()
#-----------------------------------
# Poisson
# Generate Mesh
poisson_mesh = o3d.geometry.TriangleMesh.create_from_point_cloud_poisson(pcd, depth=8, width=0, scale=1.1, linear_fit=False)[0]
# Trim the fat:
bbox = pcd.get_axis_aligned_bounding_box()
p_mesh_crop = poisson_mesh.crop(bbox)
#-----------------------------------
# Export
# http://www.open3d.org/docs/release/tutorial/geometry/file_io.html
o3d.io.write_triangle_mesh(output_path+"/bpa_mesh.obj", dec_mesh)
o3d.io.write_triangle_mesh(output_path+"/p_mesh_c.obj", p_mesh_crop)
}}}
! Install
* https://pypi.org/project/opencv-python/
* https://anaconda.org/conda-forge/opencv
Install via [[Conda|Anaconda Fundamentals]] or [[pip|Installing Python Packages]]
{{{
> conda install -c conda-forge opencv
}}}
{{{
> pip install opencv-python
}}}
Set of instructions to install (for Raspberry Pi on Linux):
*https://github.com/Guzunty/Pi/wiki/PiTeR-and-OpenCV
! Examples
* https://geekyhumans.com/detect-the-age-and-gender-of-a-face-using-opencv/
* http://www.pyimagesearch.com/
From [[this blog post|http://tartley.com/?p=1312]]
*[[Learning Modern 3D Graphics Programming Through OpenGL|http://www.arcsynthesis.org/gltut/index.html]] (C)
*[[An intro to modern OpenGL|http://duriansoftware.com/joe/An-intro-to-modern-OpenGL.-Table-of-Contents.html]] (C)
*[[Learning WebGL|http://learningwebgl.com/blog/?category_name=lessons]] (Javascript)
And, there is the first link slowly being ported to Python:
*[[https://bitbucket.org/tartley/gltutpy]]
"OpenImageIO (OIIO) is a library for reading, writing, and processing images in a wide variety of file formats, using a format-agnostic API. OIIO emphasizes formats and functionality used in professional, large-scale visual effects and feature film animation, and it is used ubiquitously by large VFX studios, as well as incorporated into many commercial products."
* https://openimageio.readthedocs.io/en/release-2.1.15.0-docs1/index.html
* https://openimageio.readthedocs.io/en/release-2.1.15.0-docs1/pythonbindings.html
!Python API
Example provided to me showing how to query min/max values of an alpha channel:
{{{
import OpenImageIO as oiio
txfile = "c:/path/to/my/image/tga"
CACHE = oiio.ImageCache.create(True)
configspec = oiio.ImageSpec()
configspec.attribute("oiio:UnassociatedAlpha", 1)
# Syntax is a little weird here, but done so the alpha isn't premultiplied
buf = oiio.ImageBuf()
buf.reset(txfile, 0, 0, configspec)
if buf.spec().nchannels > 3:
# Isolate the alpha (might not need to but may not compute correct min/max if not isolated)
alpha = oiio.ImageBuf()
oiio.ImageBufAlgo.channels(alpha, buf, ('A',))
# Compute pixel stats
stats = oiio.PixelStats()
oiio.ImageBufAlgo.computePixelStats(stats, alpha)
print ('min', stats.min)
print ('max', stats.max)
# Invalidate the image cache so updates can be read
CACHE.invalidate(txfile)
}}}
!Command line
Many command line options. Here, we query a bunch of info on an image:
{{{
> oiiotool.exe -v --info untitled_1.png
Reading untitled_1.png
untitled_1.png : 960 x 540, 3 channel, uint16 png
channel list: R, G, B
arnold/host/name: "WARPCAT"
arnold/host/hw: "1 x Intel(R) Xeon(R) W-2145 CPU @ 3.70GHz (8 cores, 16 logical) with 65211MB"
arnold/host/os: ""
arnold/version: "Arnold 5.3.1.1 [ab89cffa] windows icc-17.0.2 oiio-2.1.0 osl-1.11.0 vdb-4.0.0 clm-1.0.3.513 rlm-12.4.2 optix-6.0.0 2019/06/04 08:43:01"
arnold/license_state: "valid"
arnold/stats/date: "Tue Jun 16 08:56:24 2020"
arnold/color_manager: "color_manager_syncolor"
arnold/color_space: "scene-linear Rec 709/sRGB"
arnold/aovs/RGBA/source: "RGBA"
arnold/aovs/RGBA/filter: "gaussian_filter"
arnold/aovs/RGBA/lpe_expression: "C.*"
ResolutionUnit: "none"
XResolution: 100
YResolution: 100
}}}
Common class methods. See Python docs here:
http://docs.python.org/reference/datamodel.html#new-style-and-classic-classes
----
{{{__init__}}}
http://docs.python.org/reference/datamodel.html#object.__init__
Called when the instance is created. Probably the most popular type of operator overloader, but not required. Makes it easy to setup default states for your object, and can receive passed in arguments. See examples below.
----
{{{__call__}}}
http://docs.python.org/reference/datamodel.html#object.__call__
Allows an object to be called like a function.
----
{{{__str__}}}
http://docs.python.org/reference/datamodel.html#object.__str__
From docs:
<<<
Called by the {{{str()}}} built-in function and by the {{{print}}} statement to compute the “informal” string representation of an object. This differs from {{{__repr__()}}} in that it does not have to be a valid Python expression: a more convenient or concise representation may be used instead. The return value must be a string object.
<<<
----
{{{__repr__}}}
I've heard these called 'reproduction strings'.
http://docs.python.org/reference/datamodel.html#object.__repr__
From docs:
<<<
Called by the repr() built-in function and by string conversions (reverse quotes) to compute the “official” string representation of an object.
<<<
----
{{{__del__}}}
http://docs.python.org/reference/datamodel.html#object.__del__
From docs:
<<<
Called when the instance is about to be destroyed. This is also called a destructor.
<<<
----
{{{__nonzero__}}}
http://docs.python.org/reference/datamodel.html#object.__nonzero__
<<<
Called to implement truth value testing and the built-in operation bool(); should return False or True, or their integer equivalents 0 or 1.
<<<
See: [[How can I do truth value testing on my object?]]
----
Example:
{{{
class MyObj(object):
def __init__(self, answer):
# Executed to when an object is first instanced
self.value = answer
def __call__(self, word):
# Exected to when an object is called to.
return self.value + " " + word
def __str__(self):
# Executed when an object is 'printed'
return "CallMe"
def __repr__(self):
# Executed when called to by repr(), or with
# back-quotes:
return "<MyObj('"+self.value+"')>"
def __del__(self):
# Executed during Python garbage cleanup (when
# the object is being removed from memory)
print "Ack, " + self.__repr__() + " is dying!"
# Executes __init__
caller = MyObj("Hello?")
# Executes __call__
val = caller("Are you there?")
print val
# Hello? Are you there?
# Executes __str__
print caller
# CallMe
# Executes __repr__
print `caller`
# <MyObj('Hello?')>
# Executes __del__, since caller is being re-defined
caller = None
# Ack, CallMe('Hello?') is dying!
}}}
----
Also see:
*[[Special Methods]]
*[[How can I have objects add themselves together? Subtract one another, etc?]]
https://docs.python.org/2/library/collections.html#collections.OrderedDict
{{{
from collections import OrderedDict
d = {2:"b", 1:"a", 3:"c"}
od = OrderedDict( [ [2,"b"],
[1,"a"],
[3,"c"] ] )
print "OrderedDict:"
for key in od:
print key, od[key]
print "Dict:"
for key in d:
print key, d[key]
}}}
{{{
OrderedDict:
2 b
1 a
3 c
Dict:
1 a
2 b
3 c
}}}
No Python code yet, but the general idea is:
{{{
p4 opened -s -c (changelist) > c:\opened.txt
}}}
Then edit that text file to remove all the non-file path related stuff. Then:
{{{
c:\opened.txt | p4 -x - diff -sr | p4 -x - reopen -c 870900
}}}
Will move it into a new CL with the given #.
The bulk of these notes are pulled from [[Programming Computer Vision With Python|http://shop.oreilly.com/product/0636920022923.do]]
PIL documentation:
*http://www.pythonware.com/products/pil/
*http://www.pythonware.com/library/pil/handbook/index.htm
----
The below examples wil need this as well:
{{{
from PIL import Image
}}}
Open an image
{{{
pim = Image.open('myImage.jpg')
}}}
Show an image in the default viewer:
{{{
pim.show()
}}}
Open an image and convert it to grayscale:
I should note, when I do this, it seems to convert the images to "rainbow"... hmm...
{{{
gray = pim.convert('L')
}}}
{{{
# Extract Images for Red, Green, Blue, and Alpha:
components = pim.split()
r,g,b,a = None, None, None, None
if len(components) == 3:
r,g,b = components
else:
r,g,b,a = components
}}}
Save an image in a different format:
{{{
pim.save("myImage.tga")
}}}
Create a thumbnail:
{{{
thumb = pim.thumbnail((128,128))
}}}
Crop an image:
{{{
# (left, upper, right, lower)
box = (25, 25, 300, 300)
cropped = pim.crop(box)
}}}
Rotate a cropped region and paste:
{{{
cropped.transpose(Image.ROTATE_180)
pim.paste(cropped, box)
}}}
Resize an image:
{{{
small = pim.resize(64,64)
}}}
Rotate an image:
{{{
# Positive values are counter-clockwise:
rotated = pim.rotate(74.254)
}}}
In this example, I evaluate the pixel values in the alpha channel of an image:
* If it has no alpha channel, return False
* If all the pixels are either white, or black, return False
* If it has any other combination of values, or any other non-white/black value, return True
{{{
from PIL import Image
def alphaChannelValid(sourceFile):
image = Image.open(sourceFile)
rgba = image.split() # r,g,b,a = image
if len(rgba) != 4:
return False
# Get all the alpha values (0-255) as a list (instead of 2D array):
pixels = rgba[3].getdata()
# Remove all duplicate alpha values:
pixelSet = set(pixels)
if len(pixelSet) == 1:
pixelVal = list(pixelSet)[0]
if pixelVal in (0,255):
return False
else:
return True
else:
return True
}}}
When authoring [[Python's path|How can I set Python's path?]], another (and recomended) way of accessing your code is through //packages//.
Official docs:
http://docs.python.org/tutorial/modules.html#packages
Supporting module {{{pkgutil}}}:
http://docs.python.org/library/pkgutil.html
In a nutshell, packages allow you to access code in subdirectories without having to actually define all of those subdirs as part of your path. All you have to do is two things:
#Make sure the //parental// dir is in the path.
#In each dir that is part of the package, add an {{{__init__.py}}} module. It can be an empty module (but check the docs for useful things you //can// put in there).
Example: Presume this is your dir structure:
*\root
**\pylib
***\files
***\rigging
***\images
{{{\root}}} is in your path (and it does //not// have an {{{__init__.py}}} module). All its subdirs have an {{{__init__.py}}} file saved in them. Each of the child dirs also has a suite of python modules. In your code, you could then access the modules through 'dot notation':
{{{
import pylib.files.moduleA
from pylib.rigging import moduleB
# then execute:
pylib.files.moduleA(someArg)
moduleB(someArg)
}}}
This is just a quick overview, check the above linked docs for more.
----
''Relative Imports''
You can do relative imports with packages.
Here are [[docs|http://docs.python.org/tutorial/modules.html#intra-package-references]]
Using paths from the above example:
{{{
# Where this module is saved:
# pylib.rigging.rig.py
# or could be thought of as:
# /root/pylib/rigging/rig.py
# These two are the same, and they're looking for a module called
# someModule.py in /rigging (same dir as this module)
import someModule
from . import someModule
# This looks a dir up in /pylib for someOtherModule.py
from .. import someOtherModule
}}}
This will turn strings into Pandas 'categories', which is useful for machine learning.
https://pandas.pydata.org/pandas-docs/stable/user_guide/categorical.html
https://pandas.pydata.org/docs/reference/api/pandas.Categorical.html
{{{
for label,content in df.items():
if pd.api.types.is_string_dtype(content):
df[label] = content.astype("category").cat.as_ordered()
}}}
Use this to see what the corresponding numeric values of the categories are (for example):
{{{
df["someColumn"].cat.codes
}}}
https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.copy.html
{{{
df_tmp = df.copy()
}}}
Presuming your dataframe is called {{{df}}}:
! Find anything 'not a number':
https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.isna.html
{{{
df.isna().sum()
auctioneerID 20136
YearMade 0
MachineHoursCurrentMeter 265194
...
}}}
! Turn categorical values into numbers and fill missing:
{{{
# Turn categorical variables into numbers and fill missing:
for label, content in df.items():
if not pd.api.types.is_numeric_dtype(content):
# add a binary colum to indicate if sample had missing value
df[label+"_is_missing"] = pd.isnull(content)
# turn categories into numbers and add +1
df[label] = pd.Categorical(content).codes + 1
# Why the +1? Since Pandas auto-assigns a -1 to any category that
# has missing values, and we don't want that, we want 0.
}}}
* Released Jan, 2008, under active development.
* https://pandas.pydata.org/
* https://pandas.pydata.org/docs/getting_started/index.html
* https://pandas.pydata.org/docs/user_guide/index.html
* https://pandas.pydata.org/docs/reference/index.html
* https://pandas.pydata.org/pandas-docs/stable/user_guide/10min.html
* https://pandas.pydata.org/pandas-docs/stable/user_guide/missing_data.html
Cheat Sheets:
* https://www.datacamp.com/community/blog/python-pandas-cheat-sheet
Why is it called Pandas?
* [[Per Wikipedia|https://en.wikipedia.org/wiki/Pandas_(software)]] : The name is derived from the term "panel data", an econometrics term for data sets that include observations over multiple time periods for the same individuals.
Pandas is a ‘Data Analysis Library’
* Use it to explore, analyse, and manipulate data, to get it ready for ML.
Why Pandas?
* Simple to use.
* Integrated with many other Python ML tools
* Helps you get your data ready for ML.
* Allows importing data from various file formats such as CSV, JSON, SQL, Microsoft Excel.
{{{
# common import
import pandas as pd
}}}
!Series
* https://pandas.pydata.org/docs/reference/series.html
1-dimensional
{{{
series = pd.Series(["BMW", "Toyota", "Honda"])
colours = pd.Series(["Red", "Blue", "White"])
# Passing in an index the same length as the series will assign 'locations' to those series items.
animals = pd.Series(["cat", "dog", "bird", "panda", "snake"],
index=[0,3,9,8,3])
# what is in 'location 3 based on the indices assigned at time of creation?
animals.loc[3] # Another Series of things with that index: dog & snake
# This takes the 'positional index', as if it was a list:
animals.iloc[3] # "panda"
# loc & iloc also support Python slicing
.
# Plotting via Matplotlib integration via the Series methods, but this only works if it's numeric data!
# matplotlib.axes._subplots.AxesSubplot
animals.plot() # simple line
animals.hist() # Histagram plot :stacked blocks
# Create a range of dates, based on the lenght of some parental DataFrame:
dateRange = pd.date_range("12/24/2020", periods=len(myDataFrame))
#------------------------
# Converting data: These 'prices' are basically strings like "$370.35", so we need to convert to int/float.
# This is done via the pandas.core.strings.StringMethods '.str.replace' advanced options for replace formatting:
new_car_sales["Price"] = car_sales["Price"].str.replace('[\$\,\.]', '')
# This would give us a string up "37035"
new_car_sales["Price"] = car_sales["Price"].str[:-2]
# This would give us a string of "370"
new_car_sales["Price"] = new_car_sales["Price"].astype(int)
# Which would give us an int of 370
# Or this, to keep the floating point values:
new_car_sales["Price"] = car_sales["Price"].str.replace('[\$\,]', '').astype(float)
# Which would give you 370.35
#Basically, any method you can use on a regular python string, you can use on columns in Pandas:
series.str.lower()
# Another way of converting from formatted string to float
# For example: Maybe the values are string, like "$370.35", but you want to convert to a float:
series = series.str.replace("[\$\,]", "")
# Which would give you "370.35"
# and remove the last two values:
series = pd.to_numeric(series)
# Which would give you a float of 370.35
}}}
!~DataFrame
* https://pandas.pydata.org/docs/reference/frame.html
2-dimensional : Takes a dict categories headers (“keys”), and their column of data (list of values).
{{{
car_data = pd.DataFrame({"Car make":series, "Colour":colours})
# Info on that DataFrame
car_data.dtypes
# Columns as a list (Index instance)
car_sales.columns
# Rows
car_sales.index # Is a RangeIndex instance:
# RangeIndex(start=0, stop=10, step=1)
# Get info on numric data:
car_data.describe()
# Print the XY info for this:
car_data.info()
# The average of your numerical columns, also works directly on Series:
car_sales.mean()
# add'em up
car_sales.sum()
# Access a column as a Series:
bmws = car_sales["BMW"] # Series
bmws = car_sales.BMW # Same thing
# Filter the result by type & get a new DataFrame
car_sales[car_sales["Make"] == "Toyota"]
car_sales[car_sales["Odometer (KM)"] > 100000]
# The number of rows:
rowNum = len(car_sales)
# Print the top 5 rows of your DataFrame: Quick snapshot of your data.
car_sales.head()
car_sales.head(10) # top 10 rows.
# Print the bottom 5 rows:
car_sales.tail()
# Get indexed data, see notes on Series above:
car_sales.loc[3]
car_sales.iloc[3]
# Cross two columns together, to compare their data, and tell you how many you have of each.
pd.crosstab(car_sales["Make"], car_sales["Doors"])
# Make a new DataFrame grouped by Make (main Column), listing all values that can be meaned (averaged):
car_sales.groupby(["Make"]).mean()
# Sometimes your series will have missing values (NaN, Not a Number) in a column (Series):
# Here's an example of how to fill them with the mean (average) of the data that is there:
car_sales["Odometer"].fillna(car_sales["Odometer"].mean())
# But that just prints it, not assigns it. Two ways:
car_sales_missing["Odometer"] = car_sales["Odometer"].fillna(car_sales["Odometer"].mean())
car_sales_missing["Odometer"].fillna(car_sales_missing["Odometer"].mean(),
inplace=True) # inpalce=True modifies in place
# Create a new column:
car_sales["Seats"] = pd.Series([5,5,5,5,5])
# But this will only fill the first 5 values, and the rest are NaN : Need to fill them in per above.
# You can also assign a list directly, but must have the same number of items as there are rows.
# Create a new column where all values are the same:
car_sales["Number of wheels"] = 4
# Remove any columns with NaN values:
car_sales.dropna(inplace=True)
# Remove a row (axis=0), or column (axis=1)
car_sales.drop("Number of Wheels", axis=1)
# Shuffle your rows : Can be important for ML
# 1 = 100% of the data. .5 = 50% of the data. Why not all? If you have a lot of data, you
# can experiment on only small parts of it.
car_sales.sample(frac=1)
# Sort by index again:
car_sales_shuffled.reset_index(drop=True) # drop=True doesn't add a new index column.
#Apply a function to a column (Series):
car_sales["Odometer (KM)"] = car_sales["Odometer (KM)"].apply(lambda x: x / 1.6) # convert from km to miles.
# Rename column names:
car_sales.rename(columns={"Odometer (KM)":"Odometer (Miles)"}, inplace=True)
}}}
{{{axis=0}}} is Row (x)
{{{axis=1}}} is Column (y)
!CSV Data
{{{
my_data = pd.read_csv("my-data.csv") # DataFrame
# If from github, be sure to use the 'raw' format:
my_data = pd.read_csv("https://raw.githubusercontent.com/mrdbourke/zero-to-mastery-ml/master/data/car-sales.csv")
new_data.to_csv("exported-car-sales.csv", index=False)
# new_data.to_excel()
}}}
! Working with ~NumPy:
~NumPy is the back-end of Pandas, and you can pass ~NumPy array's to Pandas DataFrames:
{{{
import numpy as np
a2 = np.array([[1, 2.0,3.3],
[4,5,6.5]])
df = pd.DataFrame(a2)
}}}
For a given column, how many times does each value show up?
https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.value_counts.html
{{{
df["state"].value_counts()
Florida 67320
Texas 53110
California 29761
Washington 16222
Georgia 14633
Maryland 13322
Mississippi 13240
...
}}}
CSV data is basically rows and coluns of text. When Pandas imports it, you can have it process the column with dates to give you more informaitve
https://pandas.pydata.org/docs/reference/api/pandas.read_csv.html
https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.to_datetime.html
https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html
https://numpy.org/doc/stable/reference/arrays.datetime.html
{{{
import pandas as pd
df = pd.read_csv(myCsv, parse_dates=["columNameWithDates"])
df["columNameWithDates"].dtype
dtype('<M8[ns]')
}}}
FYI {{{dtype('<M8[ns]')}}} == {{{dtype: datetime64[ns]}}}
!Sort by datetime
Presuming you've done this first: [[Pandas : Parsing CSV, and reading dates]]
https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.sort_values.html
{{{
df.sort_values(by=["columNameWithDates"], inplace=True, ascending=True)
# print the first 20:
df["columNameWithDates"].head(20)
}}}
See if the 'types' of a given column match another type
Here, we check for string:
https://pandas.pydata.org/docs/reference/general_utility_functions.html
https://pandas.pydata.org/docs/reference/api/pandas.api.types.is_string_dtype.html
{{{
pd.api.types.is_string_dtype(df["MyColumnName"])
}}}
Or this:
{{{
for label, content in df.items(): # items treats a dataframe like a dictionary k:v pairs
if pd.api.types.is_string_dtype(content):
print(label)
}}}
http://code.google.com/p/py-lepton/
Good overview in the June 2009 issue of [[Python Magazine|http://pymag.phparch.com/]]
From the page:
<<<
Lepton is designed to make complex and beautiful particle effects possible, and even easy from Python programs.
Lepton provides the following core features:
*Native-code core for high-performance particle dynamics and rendering
*Pluggable particle controllers for specifying particle behavior
*Two pluggable ~OpenGL renderers, and two pygame renderers
*Spacial domains, used to control particle emission and behavior
*Easy to use and powerful texture support, including animation
*Modular architecture that lets you easily configure and customize the engine
<<<
----
Reference:
*http://www.particlesystems.org/
*http://www.opengl.org/
http://www.perforce.com/
Perforce is version control software that I use in games development. Having my animation package Maya (which supports Python scripting) interface with it is really handy. What resources exist to let Python talk to it?
----
Via ~PyPI
* https://pypi.org/project/p4python/
{{{
pip install p4python
}}}
They release their installers by version, by os:
Windows Installer (Python 2.5):
*ftp://ftp.perforce.com/perforce/r07.3/bin.ntx86/p4python25.exe
Source:
*ftp://ftp.perforce.com/perforce/r07.3/tools/p4python.tgz
Here's the root installer download page, to grab the latest version:
*ftp://ftp.perforce.com/perforce/
Documentation:
*Main Page: http://www.perforce.com/perforce/technical.html
*Python specific HTML: http://www.perforce.com/perforce/doc.current/manuals/p4script/03_python.html#1116373
*Multi-language .pdf: http://www.perforce.com/perforce/doc.current/manuals/p4script/p4script.pdf
Informative Blog Posts:
*[[Perforce Triggers in Python (part 1)|http://www.chrisevans3d.com/pub_blog/?p=55]]
*[[Perforce Triggers in Python (part 2)|http://www.chrisevans3d.com/pub_blog/?p=571]]
*[[Writing Custom Perforce Plugins in Python|http://www.chrisevans3d.com/pub_blog/?p=584]]
*[[Perforce Python API Basics|http://techarttiki.blogspot.com/2012/03/perforce-python-api-basics.html]]
The install appears to stick the modules here:
{{{
C:\Python25\Lib\site-packages\
P4.py
p4.pyc
p4.pyo
P4API.pyd
P4Python-2007.3-py2.5.egg-info
}}}
Some example code modified from their manual (they had... mistakes...)
{{{
from P4 import P4, P4Exception
p4 = P4()
p4.port = "myPort:1666" # AKA, the 'Server'
p4.user = "myName"
p4.client = "myClient" # AKA, the 'Workspace'
try:
p4.connect()
info = p4.run("info") # returns a list
d = info[0] # extract the dictionary
for key in d.keys(): # print our 'info'
print key + " : " + str(d[key])
p4.disconnect()
except P4Exception:
for e in p4.errors:
print e
}}}
----
''Notes:''
*It appears that most of P4's commands are wrappered in methods that start with {{{run_}}}, or can be called to via the {{{run()}}} method (as in the example above):
{{{
info = p4.run("info")
info = p4.run_info()
# Both appear to do the same thing.
}}}
{{{
# Both do the same thing, and can take extra args.
In this example, we change the filetypes to be saved as locked binaries:
files = p4.run_edit("-t", "binary+l", [r"c:\myFile.txt", r"c:\myFileB.txt"])
files = p4.run("edit", "-t", "binary+l", [r"c:\myFile.txt", r"c:\myFileB.txt"])
}}}
*I've also ran into issues that some commands run much faster than others based on the {{{run()}}} syntax.
*For example, {{{p4.run('print')}}} executes //much faster// than {{{p4.run_print()}}}.
----
Also see:
* [[How can I promote P4's environment variables to Windows?]]
While not specifically Python related, this post does a great job of covering concepts and pseudo-code (Python-ish) behind it:
http://freespace.virgin.net/hugo.elias/models/m_perlin.htm
And this Pygame app uses those concepts in Python:
http://www.pygame.org/project/2446/?release_id=4110
http://pexpect.readthedocs.org
From the docs:
<<<
Pexpect makes Python a better tool for controlling other applications.
Pexpect is a pure Python module for spawning child applications; controlling them; and responding to expected patterns in their output. Pexpect works like Don Libes’ Expect. Pexpect allows your script to spawn a child application and control it as if a human were typing commands.
Pexpect can be used for automating interactive applications such as ssh, ftp, passwd, telnet, etc. It can be used to a automate setup scripts for duplicating software package installations on different servers. It can be used for automated software testing. Pexpect is in the spirit of Don Libes’ Expect, but Pexpect is pure Python. Unlike other Expect-like modules for Python, Pexpect does not require TCL or Expect nor does it require C extensions to be compiled. It should work on any platform that supports the standard Python pty module. The Pexpect interface was designed to be easy to use.
<<<
Great page covering many physics topics from cloth simulation to inverse kinematics:
http://freespace.virgin.net/hugo.elias/models/m_main.htm
While not directly Python related, much of the pseudo-code supplied is easily transferrable.
Not Python related persay, but nice selection of papers here:
http://algorithmicbotany.org/papers/
In Python, it's the concept of being able to treat different types of things in the same way. Given an example:
{{{
print len("foo foo foo")
# 11
print len((4,6,32,61))
# 4
print len(["foo", "goo", "shoe"])
# 3
}}}
...you could say the {{{len}}} function is polymorphic, since it can deal with different data types like strings, tupples, or lists in the same way.
You'd think updating a pre-existing xml file with a new element and saving it would be an easy thing, right? Wrong. Well, unless I'm really missing something. It appears there's a major issue with both {{{ElementTree}}} and {{{minidom}}}: When you add a new element into a tree, it will mangle the human-readable text formatting after the file is printed\saved. While it's still a valid xml file, tags are on the wrong lines, and indentation will be off.
After a lot of troubleshooting and hunting the web, I finally figured out what was going on, and have a solution below. I've talked with a lot of people, and no one has had a better solution... but I'm surprised it's really this difficult to do it.
Below are presented two solutions, one for {{{ElementTree}}}, and one for {{{minidom}}} ({{{minidom}}} solution still doesn't solve //all// the issues). In both examples, they update the xml file with a new element called {{{<test>}}}, with the text {{{testText}}}, as a child of the element {{{<firstTagElement>}}}. I'll list code that you'd THINK would work, and the resultant file. Then I"ll show the code that you need to make it work, and the resulatant file:
''Source File'':
{{{c:/temp/foo.xml}}}
{{{
<?xml version='1.0' encoding='UTF-8'?>
<root>
<firstTagElement>
<subTagElement>some text</subTagElement>
<subTagElement>some more text</subTagElement>
</firstTagElement>
</root>
}}}
!minidom
''Bad Code:'' (Code you'd think would work, but doesn't)
{{{
import xml.dom.minidom
doc = r"c:/temp/foo.xml"
mDom= xml.dom.minidom.parse(doc)
for i in mDom.getElementsByTagName("firstTagElement"):
test = mDom.createElement("test")
tText = mDom.createTextNode("testText")
test.appendChild(tText)
i.appendChild(test)
print mDom.toxml("UTF-8")
}}}
The new file it prints is:
{{{
<?xml version="1.0" encoding="UTF-8"?><root>
<firstTagElement>
<subTagElement>some text</subTagElement>
<subTagElement>some more text</subTagElement>
<test>testText</test></firstTagElement>
</root>
}}}
Notice:
*The first {{{<root>}}} tag is on the wrong line
*The {{{<test>}}} tag has the wrong indentation level
*The closing {{{</firstTagElement>}}} is on the wrong line
----
''Good code:'' (well, sort of, it still has one bug, see below)
{{{
import xml.dom.minidom
doc = r"c:/temp/foo.xml"
mDom= xml.dom.minidom.parse(doc)
for i in mDom.getElementsByTagName("firstTagElement"):
dumbA = mDom.createTextNode(" ")
i.appendChild(dumbA)
test = mDom.createElement("test")
tText = mDom.createTextNode("testText")
test.appendChild(tText)
i.appendChild(test)
dumbB = mDom.createTextNode("\n ")
i.appendChild(dumbB)
print mDom.toxml("UTF-8")
}}}
The file it prints:
{{{
<?xml version="1.0" encoding="UTF-8"?><root>
<firstTagElement>
<subTagElement>some text</subTagElement>
<subTagElement>some more text</subTagElement>
<test>testText</test>
</firstTagElement>
</root>
}}}
Notice:
*This code is unfinished, the first {{{<root>}}} is on the wrong line. I'm currently not that sure how to fix that one... :-S
*All other problems however, are solved
*You have to create a text node before your new element, that has the tab required to place it properly in the saved xml file.
*You hav to create a text node after your new element, so that the parental element will be on the correct line, with the correct tab as well.
!~ElementTree
''Bad Code:'' (Code you'd think would work, but doesn't)
{{{
import xml.etree.ElementTree as ET
doc = "c:/temp/foo.xml"
eTree = ET.parse(doc)
firstTagElement = eTree.getroot().find("firstTagElement")
test = ET.Element("test")
test.text = "testText"
firstTagElement.append(test)
eTree.write(doc, "UTF-8")
}}}
The file it writes out is:
{{{
<?xml version='1.0' encoding='UTF-8'?>
<root>
<firstTagElement>
<subTagElement>some text</subTagElement>
<subTagElement>some more text</subTagElement>
<test>testText</test></firstTagElement>
</root>
}}}
Notice:
*Tag {{{<test>}}} has the wrong indentation level
*Tag {{{</firstTagElement>}}} is on the wrong line.
----
''Good code:''
{{{
import xml.etree.ElementTree as ET
doc = "c:/temp/foo.xml"
eTree = ET.parse(doc)
firstTagElement = eTree.getroot().find("firstTagElement")
firstTagElement[-1].tail = "\n "
test = ET.Element("test")
test.text = "testText"
test.tail = "\n "
firstTagElement.append(test)
eTree.write(doc, "UTF-8")
}}}
The file it writes out is:
{{{
<?xml version='1.0' encoding='UTF-8'?>
<root>
<firstTagElement>
<subTagElement>some text</subTagElement>
<subTagElement>some more text</subTagElement>
<test>testText</test>
</firstTagElement>
</root>
}}}
Notice:
*ALL issues resolved
*In the code, the '{{{.tail}}}' of the last element under {{{<firstTagElement>}}} is updated to have a return char with the right tab spacing for our new element.
*The new element we created also has it's '{{{.tail}}}' value set to a newline, and the correct tab level for the parental element.
!In conclusion:
Clunky!
I can't believe this is standard procedure!
[[PortablePython|http://portablepython.com/]] is, from their web page:
<<<
...a Python programming language preconfigured to run directly from any USB storage device, enabling you to have, at any time, a portable programming environment. Just download it, extract to your portable storage device or hard drive and in 10 minutes you are ready to create your next Python application.
<<<
It's built for both the 2.7 and 3.1 versions, and includes these libs built-in (at the time of this authoring):
2.7:
*~PyScripter v2.5.3
*~NymPy 1.6.1
*~SciPy 0.10.1
*Matplotlib 1.1.0
*~PyWin32 216
*Django 1.4
*PIL 1.1.7
*~Py2Exe 0.6.9
*wxPython 2.9.3.1
*~NetworkX 1.6
*Lxml 2.3
*~PySerial 2.5
*~PyODBC 3.0.2
*PyGame 1.9.1
*~PyGTK 2.24.2
*~PyQt 4.9.1-1
3.1:
*~NetworkX v1.4
*~PySerial 2.5
*~PyScripter v2.4.1
*~PyWin32 v.216
*~RPyC-3.0.7
There are a number of "Precompiled Python Distributions" available. There is a complete list [[here|http://wiki.python.org/moin/PythonDistributions]]. Two of the more popular ones are:
*[[Enthought Python Distribution|http://www.enthought.com/products/epd_free.php]] (free version)
*[[ActiveState ActivePython|http://www.activestate.com/activepython]]
*[[Portable Python|http://www.portablepython.com/]]
**A list of what packages it has can be found for each of its downloads: [[2.x|http://portablepython.com/wiki/PortablePython2.7.3.2]], [[3.x|http://portablepython.com/wiki/PortablePython3.2.1.1]] (those links are bound to stale, navigate from their home page for latest).
**It's Windows only :(
Like [[Private Methods]], by default any attribute created in a class is considered 'public': It can be modified by the methods of an object, or outside of an object. To create a attribute //private// to an object, add two underscores '{{{__}}}' before its name:
{{{
# let's make a private attribute:
class Foo(object):
def __init__(self, namer):
self.__name = namer
}}}
This is just a //convention// though, you can still access that attribute outside of the object if you want to. But //conceptually//, it's telling the programmer that it should be private, and respected as such.
Like [[Private Attributes]], you can define methods to be private. Again, you use the same 'double-underscore' '{{{__}}}' notation like attributes:
{{{
# let's make a private method:
class Foo(object):
def __private_method(self):
print "This is a private method."
def public_method(self):
print "This is a public method."
self.__private_method()
f = Foo()
f.public_method()
#This is a public method.
#This is a private method.
}}}
Like the notes from 'private attribute' above, you can actually access the 'private' method from out side the object if you wanted to. But you shouldn't, since the 'private convention' is telling the programmer explicitly //not// to do this.
Programs are the concepts behind implementing a idea. They are usually made up of one or more [[Module]]s.
http://projecteuler.net/
*"Project Euler is a series of challenging mathematical/computer programming problems that will require more than just mathematical insights to solve. Although mathematics will help you arrive at elegant and efficient methods, the use of a computer and programming skills will be required to solve most problems."
Why is this in my Python wiki? Because there are other pages devoted to the Python solutions:
*http://wiki.python.org/moin/ProblemSets/Project%20Euler%20Solutions
*http://pyeuler.wikidot.com/
Good way to understand math, and Python
"A command line tool used to obfuscate python scripts, bind obfuscated scripts to fixed machine or expire obfuscated scripts."
https://pyarmor.dashingsoft.com/
https://pyarmor.readthedocs.io/en/latest/
https://pyarmor.readthedocs.io/en/latest/installation.html
https://wiki.python.org/moin/Pyarmor
Source:
* https://github.com/dashingsoft/pyarmor-core
* https://github.com/dashingsoft/pyarmor
** https://github.com/dashingsoft/pyarmor/tree/master/plugins
* https://github.com/dashingsoft/pyarmor-webui
----
! Purchase
https://pyarmor.readthedocs.io/en/latest/license.html#purchase
The trial version only works on modules up to a certain size, and 'anyone' can generate the license files. Last I checked the cost is $52.
! Installation
https://pyarmor.readthedocs.io/en/latest/installation.html
Via pip, doesn't appear supported by Anaconda
{{{
pip install pyarmor
}}}
It is installed here under your active Python distro: {{{\Scripts\pyarmor.exe}}}
They have a web interface too:
{{{
pip install pyarmor-webui
}}}
Then to run it from the commandline:
{{{
pyarmor-webui
}}}
----
! Usage
!! Obfuscate Single Module
https://pyarmor.readthedocs.io/en/latest/usage.html#obfuscating-python-scripts
https://pyarmor.readthedocs.io/en/latest/usage.html#obfuscating-single-module
You'll want to CD into the same directory as your module:
(if you don't use {{{--exact}}}, it'll obfuscate all the modules in the same dir as the one you provided).
{{{
cd C:\path\to\my\module
pyarmor obfuscate --exact --bootstrap 3 myModule.py
}}}
(see why {{{--bootstrap 3}}} in the bugs section below).
This will create
* {{{C:\path\to\my\module\dist\}}}
** {{{myModule.py}}} <- obfuscate code
** {{{\pytransform}}}
*** {{{__init__.py}}}
*** {{{_pytransform.dll}}}
You can now distribute the module and {{{\pytransform}}} subdir inside of {{{\dist}}}.
!! Obfuscate Entire Package
https://pyarmor.readthedocs.io/en/latest/usage.html#obfuscating-whole-package
You'll want to execute this code in the directory above your package
{{{
cd C:\path\to\parentDir
pyarmor obfuscate --recursive --bootstrap 3 --output dist/myPackage myPackage/__init__.py
}}}
(see why {{{--bootstrap 3}}} in the bugs section below).
You can now distribute the package inside of {{{\dist}}}.
!! Packing Modules / Packages
https://pyarmor.readthedocs.io/en/latest/man.html#pack
'Packing' will turn your module/package into a self-contained exe.
Simple example:
{{{
pyarmor pack -e " -F" myModule.py
}}}
Which will create {{{/dist/myModule.exe}}}
----
! Generating Licenses
https://pyarmor.dashingsoft.com/#quick-start
https://pyarmor.readthedocs.io/en/latest/man.html#licenses
NOTE: (from above docs):
* "Since v6.3.0, the license.lic has been embedded into binary libraries by default"
* You'll see in some of their docs a license file in the {{{/dist}}} folder: That's the 'old way' of distributing them.
First, get information about the hardware via:
https://pyarmor.readthedocs.io/en/latest/man.html#hdinfo
If you're gathering this info from someone else and they don't have ~PyArmor / {{{hdinfo}}} installed, they can download a standalone app of it here, per-platform, which can be ran in a shell:
* https://github.com/dashingsoft/pyarmor-core#hdinfo
Or via the command line, if ~PyArmor is installed
{{{
pyarmor hdinfo
}}}
Which will print something like this:
{{{
Serial number of default harddisk: "X7IEDSWAS"
Serial number with disk name:
"/0: X7IEDSWAS"
"/1:174401413301"
Default Mac address: "70:f1:a1:23:f0:94"
Multiple Mac addresses: "<70:f1:a1:23:f0:94,70:85:01:ca:d9:5a,56:85:00:ca:d9:5c,70:85:00:cb:d9:5b>"
Ip address: "202.10.2.52"
}}}
Then you can generate a license via the below code, omitting any of the flags as needed, where {{{r001}}} is the license name: Should probably get more creative?
* {{{--expired}}} : "year-month-day"
* {{{--bind-disk}}} : Use the 'Serial number of default harddisk'.
* {{{--bind-mac}}} : Either the "Default Mac address" string, or the "Multiple Mac addresses:" string. Can this be used to bind to multiple PC's MAC addresses, to enable cross-PC support?
** Also see: [[How can I query the MAC address of my PC?]]
* {{{--bind-ipv4}}} : The 'Ip address'
Running this code will generate a /licenses subdir in your current working directory, so it's a good idea to first CD into the location of your module:
{{{
cd C:\path\to\my\module
pyarmor licenses --expired "2021-10-09" --bind-disk "100304PBN2081SF3NJ5T" --bind-mac "70:f1:a1:23:f0:94" --bind-ipv4 "202.10.2.52" r001
}}}
Your internal license data that you just generated lives here:
{{{
C:\path\to\my\module\licenses\r001
}}}
Then obfuscate your code with the license data:
{{{
pyarmor obfuscate --with-license licenses/r001/license.lic myModule.py --exact
}}}
Note, you don't supply a license with the code to the users: It's baked into the obfuscation process.
!! Generate A License For Multiple Machines Based on Hard Drive ID
https://github.com/dashingsoft/pyarmor/tree/master/plugins#example-4-create-license-for-multiple-machines
High level overview based on that example:
* Have each user run the [[hdinfo|https://github.com/dashingsoft/pyarmor-core#hdinfo]] app on their machine, providing you with the {{{Serial number of default harddisk:}}} string.
* Author a custom plugin to validate multiple machines (or work with their example module [[HERE|https://github.com/dashingsoft/pyarmor/blob/master/plugins/check_multiple_machine.py]])
** Also: See the notes on plugin errors below/
* Update your module ({{{foo.py}}}) to be obfuscated to include the special plugin hooks somewhere at the top:
{{{
# {PyArmor Plugins}
}}}
* Then, inside the main entry point in the module where code is executed ({{{main()}}} ?), add the plugin call:
{{{
# PyArmor Plugin: check_multiple_machine()
}}}
** I've found adding this outside the module won't execute it.
*While the docs say to do an //initial// obfuscation of your module with that plugin, I've found out this isn't necessary.
* Now, generate the license based on the multiple hard drive codes provided to you by your users: {{{-x}}} is 'extra' data that can be sent in:
{{{
pyarmor licenses -x "Y7IEFQEXS;1234567;someOtherHDCode" lic01
}}}
* Finally, obfuscate the module with the license data and that plugin code: Plugins are presumed relative to the module, unless an absolute path is passed in.
{{{
pyarmor obfuscate --exact --with-license licenses/lic01/license.lic --plugin ../pyarmor_plugins/check_multiple_machine.py foo.py
}}}
----
! Call ~PyArmor From Python
Normally you call ~PyArmor from the commandline, but you can do it //from// Python itself:
https://pyarmor.readthedocs.io/en/latest/advanced.html#call-pyarmor-from-python-script
{{{
from pyarmor.pyarmor import main as call_pyarmor
call_pyarmor(['obfuscate', '--recursive', '--output', 'dist', 'foo.py'])
}}}
----
!~PyArmor Plugins
~PyArmor has it's own 'plugin' system that allows you to embed extra 'plugin' code during the obfuscation process. Often used to help licensing. Docs & Examples:
https://pyarmor.readthedocs.io/en/latest/advanced.html#using-plugin-to-extend-license-type
https://pyarmor.readthedocs.io/en/latest/advanced.html#using-plugin-to-improve-security
https://pyarmor.readthedocs.io/en/latest/how-to-do.html#how-to-deal-with-plugins
@@BUGS@@ : I spent a good amount of time having trouble getting any of the examples working. You can see the conversation with the dev here:
https://github.com/dashingsoft/pyarmor/issues/595
In hindsight, this was entirely a bug on my home PC: Restarting it fixed it. And I tried it on another PC and it worked fine. But in case it ever comes up again, I'm leaving the below information here:
I //thought// the bug was in the lexer/parser they use to read the plugin code: if the last line of the plugin doesn't end with an extra line, comment, or a {{{pass}}} statement.
For example, if you try to run this code: https://github.com/dashingsoft/pyarmor/blob/master/plugins/check_multiple_machine.py
It will fail. Here's the last few lines of that module:
{{{
if _get_hd_info() not in _get_license_data().split(';'):
raise RuntimeError('This license is not for this machine')
}}}
However, if you edit the module, so it has either an extra line after the last {{{raise}}}, or insert a {{{pass}}} statement after it, or {{{# a comment}}}, it'll work:
{{{
if _get_hd_info() not in _get_license_data().split(';'):
raise RuntimeError('This license is not for this machine')
}}}
or
{{{
if _get_hd_info() not in _get_license_data().split(';'):
raise RuntimeError('This license is not for this machine')
pass
}}}
----
! Bugs In Other Apps
I tried using ~PyArmor to obfuscate some Maya Python modules. It did not go so well, but I was able to work around it.
----
''Issue #1'' : Need to uses Maya's pip to install ~PyArmor to obfuscate Maya Pythom modules (rather than some pre-existing system-level pyarmor.exe install). Otherwise you could get a {{{marshal}}} error when trying to read the byte code.
After install, need to call to it via absolute path:
{{{
cd C:\path\to\my\maya\module
"C:\Program Files\Autodesk\Maya2022\Python\Scripts\pyarmor.exe" obfuscate myMyModule.py
}}}
----
''Issue #2'' : Part of this is just new user confusion but: This only seems to happen when obfuscating a single module : Obfuscating an entire package generates the correct relative import statement: Even though I'm using Python3, ~PyArmor appears to be using Python2 base import statements. Because of that, in //Maya// the imports fail: They still seem to work fine at 'system-level' Python. In the obfuscated module ({{{myModule.py}}}, from above), you'll see this on the first line:
{{{
from pytransform import pyarmor_runtime
}}}
After logging this as a bug here: https://github.com/dashingsoft/pyarmor/issues/594
I got a reply that I need to look into the what the {{{--bootstrap}}} arg does.
https://pyarmor.readthedocs.io/en/latest/man.html#obfuscate : ctrl+f : "bootstrap":
<<<
...But the option {{{--bootstrap}}} is set to 2, the Bootstrap Code always makes absolute import without leading dots. If it is set to 3, the Bootstrap Code always makes relative import with leading dots.
<<<
So by adding {{{--bootstrap 3}}} to the above obfuscation code, you get this style of import:
{{{
from .pytransform import pyarmor_runtime
}}}
Which makes Maya happy.
Docs on similar subject here:
https://pyarmor.readthedocs.io/en/latest/understand-obfuscated-scripts.html#bootstrap-code
----
''Issue #3'' : If you're obfuscating a single module and //not// using the {{{--exact}}} flag to obfuscate only that module, //and// it's in a package with an {{{__init__.py}}} next to it, ~PyArmor will //also// obfuscate the {{{__init__.py}}} and copy it into the {{{/dist}}} folder. The issue is, that the {{{__init__.py}}} (if previously empty) will only have a single line of code in it, with no import above it:
{{{
__pyarmor__(__name__, __file__, b'\x50\x59\x41\x5......")
}}}
Which will fail on Maya import. Deleting that whole line fixes the issue.
This issue doesn't happen if obfuscating an entire package.
http://pybrain.org/pages/home
<<<
PyBrain is a modular Machine Learning Library for Python. Its goal is to offer flexible, easy-to-use yet still powerful algorithms for Machine Learning Tasks and a variety of predefined environments to test and compare your algorithms.
PyBrain is short for ~Python-Based Reinforcement Learning, Artificial Intelligence and Neural Network Library. In fact, we came up with the name first and later reverse-engineered this quite descriptive "Backronym".
<<<
''Please see my PyGame wiki here:''
http://pygamewiki.tiddlyspot.com/
It could be considered a 'sister-wiki' to this one, focusing solely on PyGame.
PyMT = Python Multitouch
http://pymt.txzone.net/
http://code.google.com/p/pymt/
*"PyMT is a python module for developing multi-touch enabled media rich applications. Currently the aim is to allow for quick and easy interaction design and rapid prototype development. "
*http://vimeo.com/3548811
*http://vimeo.com/3245665?pg=embed&sec
Requires [[pyglet]]
* [[QStyle|https://doc.qt.io/qtforpython/PySide2/QtWidgets/QStyle.html]] : Check the docs under {{{StandardPixmap}}} for a list of [[all the available icons|https://doc.qt.io/qtforpython/PySide2/QtWidgets/QStyle.html#PySide2.QtWidgets.PySide2.QtWidgets.QStyle.StandardPixmap]].
** [[QCommonStyle|https://doc.qt.io/qtforpython/PySide2/QtWidgets/QCommonStyle.html]]
{{{
from PySide2 import QtWidgets
style = QtWidgets.QCommonStyle()
downArrow = style.standardIcon(style.SP_ArrowDown)
button = QtWidgets.QPushButton(downArrow, "Has Icon!")
}}}
Any widget can have actions associated with them, that can be shown as popup menus when the mouse RMB on them. You can create separators by turning a {{{QAction}}} into one. Note they can't be reused... you need to create a unique separator for each instance. Because of this, I author a simple convenience function that creates and returns one, so they can be easily inserted into the menus.
You can create submenus by instancing {{{QMenu}}}'s.
The below example creates a popup window with two items: An action (button), a separator, and a submenu, which also has a button.
Example code
{{{
from PySide.QtGui import QWidget, QAction, QMenu
from PySide.QtCore import Qt
def separator(parent):
sep = QAction(parent)
sep.setSeparator(True)
return sep
class MyWid(QWidget):
def setupMenu(self):
self.setContextMenuPolicy(Qt.ActionsContextMenu)
# Create actions and submenus:
actA = QAction("action A", self)
actSub = QAction("Submenu", self)
subMenu = QMenu()
actB = QAction("action B", self)
# Setup menus:
self.addAction(actA)
self.addAction(separator(self))
self.addAction(actSub)
actSub.setMenu(subMenu)
subMenu.addAction(actB)
# Connect their signals to some fictitious method:
actA.triggered.connect(self.someMethodA)
actB.triggered.connect(self.someMethodB)
}}}
Docs:
*[[QWidget|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html]]
**[[addAction|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.addAction]] : Accepts [[QAction|http://srinikom.github.io/pyside-docs/PySide/QtGui/QAction.html]]
**[[setContextMenuPolicy|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.setContextMenuPolicy]] : Accepts a [[Qt.ContextMenuPolicy|http://srinikom.github.io/pyside-docs/PySide/QtCore/Qt.html]]
*[[QAction|http://srinikom.github.io/pyside-docs/PySide/QtGui/QAction.html]]
**[[triggered|http://srinikom.github.io/pyside-docs/PySide/QtGui/QAction.html#PySide.QtGui.PySide.QtGui.QAction.triggered]]
**[[setSeparator|http://srinikom.github.io/pyside-docs/PySide/QtGui/QAction.html#PySide.QtGui.PySide.QtGui.QAction.setSeparator]]
Any {{{QWidget}}} can eaily have a tooltip assigned via the [[setToolTip|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.setToolTip]] method:
{{{
myWidget.setToolTip("Tip goes here!")
}}}
To create a simple image for display:
{{{
from PySide.QtGui import *
pix = QPixmap("c:/absolute/path/to/my/image.png")
# or:
pix = QPixmap("relativeImage.png")
labelWid = QLabel()
labelWid.setPixmap(logoPix)
}}}
Notes:
*The provided path can be relative to the calling module in a native ~PySide application. I've seen in other software (like Maya) the requirement for an absolute path.
*{{{QPixmap}}}'s can also be added to any subclass of {{{QAbstractButton}}} as an icon.
Docs:
* [[QPixMap|http://srinikom.github.io/pyside-docs/PySide/QtGui/QPixmap.html]]
* [[QLabel|http://srinikom.github.io/pyside-docs/PySide/QtGui/QLabel.html]]
* [[QAbstractButton|http://srinikom.github.io/pyside-docs/PySide/QtGui/QAbstractButton.html]]
Simple boilerplate code to build a ~PySide (1) Level in Python 2.7 on Windows
{{{
import sys
from PySide import QtGui, QtCore
class Window(QtGui.QWidget):
"""
Create our special window.
"""
name = "myWindowId"
title = 'My Window Name'
def __init__(self, *args, **kwargs):
"""
Init our main window. Boilerplate, no need to modify.
"""
# Must happen before our super init:
app = QtGui.QApplication(sys.argv)
super(Window, self).__init__(*args, **kwargs)
self.setObjectName(Window.name)
self.setWindowTitle(Window.title)
self.setProperty("saveWindowPref", True) # Save prefs on exit.
self.settings = QtCore.QSettings("My Company Name", Window.name)
self.populate()
# Reload the last place/side the window was in:
self.restoreGeometry(self.settings.value("geometry", ""))
self.show()
self.activateWindow() # Make it the active window.
# self.adjustSize() # Will make window shrink to fit, may not be what you want.
# Must do, or window will hang/crash: It's what actually starts the app
# running, with all the qt ui threads & tick loops:
sys.exit(app.exec_())
def closeEvent(self, event):
"""
Overridden supeclass method: Save any settings as we close the window.
"""
# Save the last place/size the window was in:
self.settings.setValue("geometry", self.saveGeometry())
event.accept()
def populate(self):
"""
Create the primary contents of our Window/Widget.
"""
self.layout_main = QtGui.QVBoxLayout(self)
widget_button = QtGui.QPushButton()
widget_button.setText("My Awesome Button")
self.layout_main.addWidget(widget_button)
if __name__ == "__main__":
Window()
}}}
You can use a css-style format for setting the background color of widgets:
{{{
myWidget.setStyleSheet("background-color: rgb(200,200,64)")
myWidget.setStyleSheet("background-color: gray")
}}}
This changes the background color, and the font color a the same time, using color names (see links below). Note, the string names are case insensitive.
{{{
myWidget.setStyleSheet("background-color: LightSteelBlue; color:Black")
}}}
Style sheet values are inherited by all children. If you want to ''revert some child widget back to system defaults'', you can do something like this:
{{{
myWidget.setStyleSheet("background-color: palette(window)")
}}}
Slightly more complex:
https://forums.autodesk.com/t5/maya-programming/maya-pyside-buttons-not-pressing-in-2016-if-using-background/td-p/5694408
{{{
COLOR_BUT_BORDER = (80,80,80) # The color of button borders
class Button(QtWidgets.QPushButton):
"""
Make a QPushButton, with a nice border.
"""
def __init__(self, *args, **kwargs):
super(Button, self).__init__(*args, **kwargs)
self.setStyleSheet(("QPushButton{border-color:rgb(%s,%s,%s); border-width: 2px; border-style: outset;} "%(COLOR_BUT_BORDER[0], COLOR_BUT_BORDER[1], COLOR_BUT_BORDER[2])+
"QPushButton:hover{background-color: gray; color: black; border: black 2px} "+
"QPushButton:pressed{background-color: white; color: black; border: black 2px}"))
}}}
https://www.w3schools.com/cssref/
[[QWidget.setStyleSheet|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.setStyleSheet]] docs
[[CSS background color|http://www.w3schools.com/cssref/pr_background-color.asp]] docs
[[CSS general color names|https://www.w3schools.com/colors/colors_names.asp]]
As I learn the language, shortcut to commonly used docs and classes.
!!!Qt
*[[Qt Project Docs|http://qt-project.org/doc/]]
*[[Qt Widget Gallery|http://qt-project.org/doc/qt-4.8/gallery.html]]
*[[Qt Widgets and Layouts|http://qt-project.org/doc/qt-4.8/widgets-and-layouts.html]]
*[[Qt Project PySide Documentation|http://qt-project.org/wiki/PySideDocumentation]]
!!!~PySide
Tutorials:
*[[PySide tutorials|http://qt-project.org/wiki/PySide_Tutorials]]
*[[ZetCode PySide tutorials|http://zetcode.com/gui/pysidetutorial]]
Docs:
*[[PySide docs|http://srinikom.github.io/pyside-docs/index.html]]
*[[QtCore|http://srinikom.github.io/pyside-docs/PySide/QtCore/index.html]]
**[[QEvent|http://srinikom.github.io/pyside-docs/PySide/QtCore/QEvent.html]] - Also see [[PySide : Events]]
**[[QLine|http://srinikom.github.io/pyside-docs/PySide/QtCore/QLine.html]]
**[[QObject|http://srinikom.github.io/pyside-docs/PySide/QtCore/QObject.html]] - The base class of all Qt objects
***[[QCoreApplication|http://srinikom.github.io/pyside-docs/PySide/QtCore/QCoreApplication.html]] - provides an event loop for console Qt applications.
**[[QPoint|http://srinikom.github.io/pyside-docs/PySide/QtCore/QPoint.html]]
**[[QRect|http://srinikom.github.io/pyside-docs/PySide/QtCore/QRect.html]]
**[[QSize|http://srinikom.github.io/pyside-docs/PySide/QtCore/QSize.html]]
**[[QSettings|http://srinikom.github.io/pyside-docs/PySide/QtCore/QSettings.html]]
**[[Qt|http://srinikom.github.io/pyside-docs/PySide/QtCore/Qt.html]] - Namespace with many miscellaneous identifiers.
**[[Signal|http://srinikom.github.io/pyside-docs/PySide/QtCore/Signal.html]]
**[[Slot|http://srinikom.github.io/pyside-docs/PySide/QtCore/Slot.html]]
*[[QtGui|http://srinikom.github.io/pyside-docs/PySide/QtGui/index.html]]
**[[QAction|http://srinikom.github.io/pyside-docs/PySide/QtGui/QAction.html]] - provides an abstract user interface action that can be inserted into widgets - Inherited from {{{QObject}}}.
**[[QApplication|http://srinikom.github.io/pyside-docs/PySide/QtGui/QApplication.html]] - Manages the GUI application’s control flow and main settings - Inherits from [[QtCore.QCoreApplication|http://srinikom.github.io/pyside-docs/PySide/QtCore/QCoreApplication.html]]
**[[QBrush|http://srinikom.github.io/pyside-docs/PySide/QtGui/QBrush.html]] - defines the fill pattern of shapes drawn by {{{QtGui.QPainter}}}.
**[[QColor|http://srinikom.github.io/pyside-docs/PySide/QtGui/QColor.html]]
**[[QFont|http://srinikom.github.io/pyside-docs/PySide/QtGui/QFont.html]]
**[[QGradient|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGradient.html]]
***[[QConicalGradient|http://srinikom.github.io/pyside-docs/PySide/QtGui/QConicalGradient.html]]
***[[QLinearGradient|http://srinikom.github.io/pyside-docs/PySide/QtGui/QLinearGradient.html]]
***[[QRadialGradient|http://srinikom.github.io/pyside-docs/PySide/QtGui/QRadialGradient.html]]
**[[QGraphicsItem|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsItem.html]] - the base class for all graphical items in a {{{QtGui.QGraphicsScene}}}. Also see [[PySide : QGraphics]].
**[[QGraphicsScene|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsScene.html]] - provides a surface for managing a large number of 2D graphical items. Also see [[PySide : QGraphics]]
**[[QIcon|http://srinikom.github.io/pyside-docs/PySide/QtGui/QIcon.html]] - Provides scalable icons, can be used in buttons inheriting from {{{QAbstractButton}}}.
**[[QInputEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QInputEvent.html]] - Also inherits from [[QEvent|http://srinikom.github.io/pyside-docs/PySide/QtCore/QEvent.html]] - Also see [[PySide : Events]]
***[[QMouseEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QMouseEvent.html]]
***[[QWheelEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWheelEvent.html]]
**[[QLayoutItem|http://srinikom.github.io/pyside-docs/PySide/QtGui/QLayoutItem.html]] - Also see [[PySide : Layout Managers]]
***[[QLayout|http://srinikom.github.io/pyside-docs/PySide/QtGui/QLayout.html]] - Also inherits from {{{QObject}}} - base class of geometry managers.
****[[QBoxLayout|http://srinikom.github.io/pyside-docs/PySide/QtGui/QBoxLayout.html]] - lines up child widgets horizontally or vertically
*****[[QHBoxLayout|http://srinikom.github.io/pyside-docs/PySide/QtGui/QHBoxLayout.html]] - construct horizontal box layout objects
*****[[QVBoxLayout|http://srinikom.github.io/pyside-docs/PySide/QtGui/QVBoxLayout.html]] - lines up widgets vertically
****[[QFormLayout|http://srinikom.github.io/pyside-docs/PySide/QtGui/QFormLayout.html]] - manages forms of input widgets and their associated labels.
****[[QGridLayout|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGridLayout.html]] - lays out widgets in a grid
****[[QStackedLayout|http://srinikom.github.io/pyside-docs/PySide/QtGui/QStackedLayout.html]] - provides a stack of widgets where only one widget is visible at a time.
***[[QSpacerItem|http://srinikom.github.io/pyside-docs/PySide/QtGui/QSpacerItem.html]] - Provides blank space in a layout, what is inserted when the a 'spacing' or 'stretch' method is called to in a layout.
**[[QPaintDevice|http://srinikom.github.io/pyside-docs/PySide/QtGui/QPaintDevice.html]] - The base class of objects that can be painted.
***[[QImage|http://srinikom.github.io/pyside-docs/PySide/QtGui/QImage.html]] - Provides a hardware-independent image representation that allows direct access to the pixel data, and can be used as a paint device
***[[QPicture|http://srinikom.github.io/pyside-docs/PySide/QtGui/QPicture.html]] - a paint device that records and replays {{{QtGui.QPainter}}} commands.
***[[QPixmap|http://srinikom.github.io/pyside-docs/PySide/QtGui/QPixmap.html]] - an off-screen image representation that can be used as a paint device.
****[[QBitmap|http://srinikom.github.io/pyside-docs/PySide/QtGui/QBitmap.html]] - provides monochrome (1-bit depth) pixmaps
***''[[QWidget|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html]]'' - Also inherits from {{{QObject}}}. List of [[Widget event methods|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#events]].
****[[QAbstractButton|http://srinikom.github.io/pyside-docs/PySide/QtGui/QAbstractButton.html]]
*****[[QCheckBox|http://srinikom.github.io/pyside-docs/PySide/QtGui/QCheckBox.html]]
*****[[QPushButton|http://srinikom.github.io/pyside-docs/PySide/QtGui/QPushButton.html]]
*****[[QRadioButton|http://srinikom.github.io/pyside-docs/PySide/QtGui/QRadioButton.html]]
*****[[QToolButton|http://srinikom.github.io/pyside-docs/PySide/QtGui/QToolButton.html]] - Provides a quick-access button to commands or options, usually used inside a {{{QToolBar}}}.
****[[QDialog|http://srinikom.github.io/pyside-docs/PySide/QtGui/QDialog.html]] - Base class of dialog windows.
*****[[QFileDialog|http://srinikom.github.io/pyside-docs/PySide/QtGui/QFileDialog.html]] - Provides a dialog that allow users to select files or directories.
*****[[QProgressDialog|http://srinikom.github.io/pyside-docs/PySide/QtGui/QProgressDialog.html]] - provides feedback on the progress of a slow operation.
*****[[QMessageBox|http://srinikom.github.io/pyside-docs/PySide/QtGui/QMessageBox.html]] - Provides a //modal dialog// for informing the user or for asking the user a question and receiving an answer.
*****[[QInputDialog|http://srinikom.github.io/pyside-docs/PySide/QtGui/QInputDialog.html]]
****[[QFrame|http://srinikom.github.io/pyside-docs/PySide/QtGui/QFrame.html]] - Container layout with border.
*****[[QAbstractScrollArea|http://srinikom.github.io/pyside-docs/PySide/QtGui/QAbstractScrollArea.html]] - provides a scrolling area with on-demand scroll bars
******[[QGraphicsView|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsView.html]] - provides a widget for displaying the contents of a {{{QtGui.QGraphicsScene}}}.
******[[QScrollArea|http://srinikom.github.io/pyside-docs/PySide/QtGui/QScrollArea.html]] - provides a scrolling view onto another widget
******[[QTextEdit|http://srinikom.github.io/pyside-docs/PySide/QtGui/QTextEdit.html]] - a widget that is used to edit and display both plain and rich text.
*******[[QTextBrowser|http://srinikom.github.io/pyside-docs/PySide/QtGui/QTextBrowser.html]] - provides a rich text browser with hypertext navigation.
*****[[QLabel|http://srinikom.github.io/pyside-docs/PySide/QtGui/QLabel.html]] - Provides a text or image display
****[[QMenu|http://srinikom.github.io/pyside-docs/PySide/QtGui/QMenu.html]] - Creates a popup menu.
****[[QMenuBar|http://srinikom.github.io/pyside-docs/PySide/QtGui/QMenuBar.html]]
****[[QProgressBar|http://srinikom.github.io/pyside-docs/PySide/QtGui/QProgressBar.html]]
****[[QStatusBar|http://srinikom.github.io/pyside-docs/PySide/QtGui/QStatusBar.html]]
**[[QPainter|http://srinikom.github.io/pyside-docs/PySide/QtGui/QPainter.html]] - Used for custom painting/drawing in a widget. Also see [[PySide : QPainter]]
**[[QPen|http://srinikom.github.io/pyside-docs/PySide/QtGui/QPen.html]] - Defines how a {{{QtGui.QPainter}}} should draw lines and outlines of shapes.
**[[QResizeEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QResizeEvent.html]] - Also inherits from {{{QEvent}}}
**[[QSizePolicy|http://srinikom.github.io/pyside-docs/PySide/QtGui/QSizePolicy.html]] - Is a layout attribute describing horizontal and vertical resizing policy
**[[QToolTip|http://srinikom.github.io/pyside-docs/PySide/QtGui/QToolTip.html]] - provides tool tips (balloon help) for any widget
**[[QToolBar|http://srinikom.github.io/pyside-docs/PySide/QtGui/QToolBar.html]]
I'm used to easily creating "separator" elements in other gui toolkits: Horizontal lines that separate items visually. Didn't seem to find a way to do it in PySide easily, came up with this:
{{{
from PySide.QtGui import QFrame
def widgetSeparator():
"""
Creates a separator that can be used to split up widgets.
Return: QFrame.
"""
f = QFrame()
f.setFrameStyle(QFrame.HLine)
f.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum)
return f
}}}
To use it:
{{{
someLayout.addWidget(widgetSeparator())
}}}
----
Also:
{{{
from PySide.QtGui import QFrame
vSeparator = QFrame(self)
vSeparator.setFrameShape(QFrame.VLine)
hSeparator = QFrame(self)
hSeparator.setFrameShape(QFrame.HLine)
}}}
* http://srinikom.github.io/pyside-docs/PySide/QtGui/QFrame.html
All below classes inherit fromt this {{{QDialog}}} herarchy
*[[QObject|http://srinikom.github.io/pyside-docs/PySide/QtCore/QObject.html]] - the base class of all Qt objects
*[[QPaintDevice|http://srinikom.github.io/pyside-docs/PySide/QtGui/QPaintDevice.html]] - the base class of objects that can be painted
**[[QWidget|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html]] - the base class of all user interface objects
***[[QDialog|http://srinikom.github.io/pyside-docs/PySide/QtGui/QDialog.html]] - the base class of dialog windows
They are:
*[[QFileDialog|http://srinikom.github.io/pyside-docs/PySide/QtGui/QFileDialog.html]]
** What has convenience static methods for:
** [[getOpenFileName|http://srinikom.github.io/pyside-docs/PySide/QtGui/QFileDialog.html#PySide.QtGui.PySide.QtGui.QFileDialog.getOpenFileName]] : Get the name of a single existing file.
** [[getOpenFileNames|http://srinikom.github.io/pyside-docs/PySide/QtGui/QFileDialog.html#PySide.QtGui.PySide.QtGui.QFileDialog.getOpenFileNames]] : Get the name of one or more existing files.
** [[getExistingDirectory|http://srinikom.github.io/pyside-docs/PySide/QtGui/QFileDialog.html#PySide.QtGui.PySide.QtGui.QFileDialog.getExistingDirectory]] : Get the name of a directory.
** [[getSaveFileName|http://srinikom.github.io/pyside-docs/PySide/QtGui/QFileDialog.html#PySide.QtGui.PySide.QtGui.QFileDialog.getSaveFileName]] : Get the name of a new or existing file (usually for save).
*[[QErrorMessage|http://srinikom.github.io/pyside-docs/PySide/QtGui/QErrorMessage.html]]
*[[QColorDialog|http://srinikom.github.io/pyside-docs/PySide/QtGui/QColorDialog.html]]
*[[QPrintDialog|http://srinikom.github.io/pyside-docs/PySide/QtGui/QPrintDialog.html]]
*[[QPageSetupDialog|http://srinikom.github.io/pyside-docs/PySide/QtGui/QPageSetupDialog.html]]
*[[QWizard|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWizard.html]]
*[[QProgressDialog|http://srinikom.github.io/pyside-docs/PySide/QtGui/QProgressDialog.html]]
*[[QPrintPreviewDialog|http://srinikom.github.io/pyside-docs/PySide/QtGui/QPrintPreviewDialog.html]]
*[[QMessageBox|http://srinikom.github.io/pyside-docs/PySide/QtGui/QMessageBox.html]]
** What has convenience static methods for:
** [[QMessageBox.about|http://srinikom.github.io/pyside-docs/PySide/QtGui/QMessageBox.html#PySide.QtGui.PySide.QtGui.QMessageBox.about]]
** [[QMessageBox.critical|http://srinikom.github.io/pyside-docs/PySide/QtGui/QMessageBox.html#PySide.QtGui.PySide.QtGui.QMessageBox.critical]]
** [[QMessageBox.information|http://srinikom.github.io/pyside-docs/PySide/QtGui/QMessageBox.html#PySide.QtGui.PySide.QtGui.QMessageBox.information]]
** [[QMessageBox.question|http://srinikom.github.io/pyside-docs/PySide/QtGui/QMessageBox.html#PySide.QtGui.PySide.QtGui.QMessageBox.question]]
** [[QMessageBox.warning|http://srinikom.github.io/pyside-docs/PySide/QtGui/QMessageBox.html#PySide.QtGui.PySide.QtGui.QMessageBox.warning]]
** It should be noted that most of these have the same function/look,it just changes which icon is displayed.
*[[QInputDialog|http://srinikom.github.io/pyside-docs/PySide/QtGui/QInputDialog.html]]
*[[QFontDialog|http://srinikom.github.io/pyside-docs/PySide/QtGui/QFontDialog.html]]
!File Browser Examples
{{{
# Note, the passing of self is to the 'parent' parameter: This can also be None to make
# a standalone dialog.
text, ok = QInputDialog().getText(self, 'Input Dialog', 'Enter your name:')
}}}
{{{
startingDir = "c:/some/directory"
filePath, fileFilter = QFileDialog.getOpenFileName(parent=self, caption="Import File",
filter="Maya Files (*.ma *.mb);;FBX (*.fbx);;Alembic (*.abc)", dir=startingDir )
}}}
{{{
startingDir = "c:/some/directory"
theDir = QtWidgets.QFileDialog.getExistingDirectory(self, dir=startingDir , caption="Choose Dir!"))
}}}
! Confirm Dialog Examples:
Note, a few things:
If this message box is a child to some window, pass in that widget (self) like so:
{{{
msgBox = QtGui.QMessageBox(self)
}}}
If this message box is being called from inside a function, certain applications can lock up. I've found that putting this code before the message box creation will fix it:
{{{
if not QtGui.QApplication.instance():
QtGui.QApplication(sys.argv)
}}}
Ask a simple question:
{{{
confirm = QtGui.QMessageBox.question(self, "confirm", "Do A thing?", QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
if confirm == QtGui.QMessageBox.No:
return
}}}
More complex:
{{{
msgBox = QtGui.QMessageBox()
msgBox.setText("Do the thing?")
msgBox.setInformativeText("Are you really sure?")
msgBox.addButton("Continue", QtGui.QMessageBox.AcceptRole)
msgBox.addButton("Cancel", QtGui.QMessageBox.RejectRole)
ret = msgBox.exec_()
if ret == QtGui.QMessageBox.RejectRole:
return
}}}
It should be noted that you can set the text to be 'rich', so you can do things like embed web links:
{{{
# If you want to use the 'text', you need to set it as RichText:
msgBox.setTextFormat(QtCore.Qt.RichText)
msgBox.setText("<a href=http://pythonwiki.tiddlyspot.com>A Link!</a>")
# Or, you can put your link in the 'informative text, and it will auto-detect without having to set it.
messageBox.setInformativeText("<a href=http://pythonwiki.tiddlyspot.com>A Link!</a>")
}}}
Difference between 'setText' and 'setInformativeText'?
* {{{setText}}} will respect retrun characters ({{{\n}}}) if it's //not// set to 'Rich Text'. Appears 'on the top' of the dailog.
* {{{setInformativeText}}} doesn't respect return characters ({{{\n}}}), but will auto-enable web links (see above). Appears 'on the bottom' of the dialog.
Since I always seem to forget:
* [[QFrame|https://doc.qt.io/qtforpython/PySide2/QtWidgets/QFrame.html]] : Provides a pretty border / visual styling.
** [[QLabel|https://doc.qt.io/qtforpython/PySide2/QtWidgets/QLabel.html]] : A single line of ''non-editable'' text. Use {{{text}}} to get the text, and {{{setText}}} to set it.
** [[QAbstractScrollArea|https://doc.qt.io/qtforpython/PySide2/QtWidgets/QAbstractScrollArea.html]]
*** [[QTextEdit|https://doc.qt.io/qtforpython/PySide2/QtWidgets/QTextEdit.html]] : Able to display multiple ''editable'' lines, auto-resize itself with scrollbar. Can also be set to {{{readOnly(True)}}}, and accept 'rich' text if needed. Use {{{toPlainText}}} to get the text, and {{{setText}}} to set it.
* [[QLineEdit|https://doc.qt.io/qtforpython/PySide2/QtWidgets/QLineEdit.html]] : A single line of ''editable text''. Can also be set to {{{setReadOnly(True)}}}. Use {{{text}}} to get the text, and {{{setText}}} to set it.
Also, if you want to limit an editor to a certain type of input, like say, numbers only, you can add validators:
[[PySide : Force QLineEdit to only accept numbers, or certain strings?]]
!!!General Overview:
Preface: I'm no expert at this.
It appears there are multiple ways to implement drag & drop (d&d) in ~PySide. In this first section, I'll describe how some of the concepts I've learned work together:
{{{QWidget}}}s and their subclasses support d&d, not //layouts//. To setup a widget to support d&d, you'll need to subclass it, then override some methods. In this example, a bare-bones {{{QWidget}}} is created that can both accept drops, and allow its data to be dropped on something else. It will print what is dropped on it.
Concepts:
* The {{{__init__}}} method has {{{setAcceptDrops}}} set to True, allowing for drops on the widget. It also stores the location to a {{{QPixmap}}} that will be drawn during the drag.
* The {{{mousePressEvent}}} is what starts the whole drag operation. It's where you create a {{{QDrag}}} instance, and store the MIME data that will exist in the drag packet. It also lets you limit which button triggers the d&d event.
* The {{{dragEnterEvent}}} Detects when a drag event enters a widget. It's where the drag event is 'accepted': If this doesn't happen, the drag will be rejected. It can be used to reject the event if it doesn't have the right type of MIME data.
* The {{{dragMoveEvent}}} detects when a drag event moves inside of a widget. We don't use it for anything in the example.
* The {{{dragLeaveEvent}}} detects when a drag event leaves a widget. We don't use it for anything in the example.
* The {{{dropEvent}}} : detects when a drag event is dropped in a widget. You can then query the MIME data that lived in the drag packet. Based on the stored {{{QDrag}}} instance (above), you can query the widget that initiated the drag, and query the widget dropped on.
Events can be 'accepted'. From the docs: "Setting the accept parameter indicates that the event receiver wants the event. Unwanted events might be propagated to the parent widget.".
Example Links:
*[[QWidget|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html]]
*[[QDrag|http://srinikom.github.io/pyside-docs/PySide/QtGui/QDrag.html]]
*[[QMimeData|http://srinikom.github.io/pyside-docs/PySide/QtCore/QMimeData.html]]
*[[QEvent|http://srinikom.github.io/pyside-docs/PySide/QtCore/QEvent.html#PySide.QtCore.PySide.QtCore.QEvent]]
*[[Qt|http://srinikom.github.io/pyside-docs/PySide/QtCore/Qt.html]] : Look under the {{{DropAction}}} section.
See below for docs on the events passed around.
{{{
from PySide import QtGui, QtCore
class MyDragAndDropWidget(QtGui.QWidget):
def __init__(self, *args):
super(MyDragAndDropWidget, self).__init__(*args)
# Allow this widget to accept drop events:
self.setAcceptDrops(True)
# You can create an image to display when the drag is happening:
pathToIcon = "c:/some/path/to/image.png"
self.pixmap = QtGui.QPixmap.fromImage(QtGui.QImage(pathToIcon))
def mousePressEvent(self, event):
"""
The drag & drop operation begins here.
"""
# You can limit which butons control the d&d. In this case, it is only
# triggered by holding the RMB:
if event.buttons() != QtCore.Qt.RightButton:
return
print "MOUSE PRESS EVENT", type(event)
# Create the drag event, binding it to this instance. Save it as an attr
# for later query during the drop.
drag = QtGui.QDrag(self)
drag.setPixmap(self.pixmap)
# Create the MIME data to pass along with the drag:
mimeData = QtCore.QMimeData()
mimeData.setText("I am MIME text!")
drag.setMimeData(mimeData)
# This sets where the icon will draw relative to the mouse position:
drag.setHotSpot(QtCore.QPoint(drag.pixmap().width()/2,
drag.pixmap().height()/2))
# This starts the drag & drop operation. The argument passed in controls what will
# with the data. In this case, it will make a copy.
dropAction = drag.start(QtCore.Qt.CopyAction)
def dragEnterEvent(self, event):
"""
A drag event has entered this widget.
This event handler is called when a drag is in progress and the mouse enters
this widget.
"""
event.accept()
print "DRAG ENTER EVENT", type(event)
# optionally you can test the event's mimeData, and only accept the event then:
#if event.mimeData().hasFormat('text/plain'):
#event.accept()
def dragMoveEvent(self, event):
"""
A drag event is moving in this widget.
This event handler is called if a drag is in progress, and when any of the
following conditions occur:
* The cursor enters this widget.
* The cursor moves within this widget.
* A modifier key is pressed on the keyboard while this widget has the focus.
"""
print "DRAG MOVE EVENT", type(event)
def dragLeaveEvent(self, event):
"""
A drag event has left this widget.
This event handler is called when a drag is in progress and the mouse leaves
this widget.
"""
print "DRAG LEAVE EVENT", type(event)
def dropEvent(self, event):
"""
This event handler is called when a drag packet is dropped on this widget.
"""
print "DROP EVENT", type(event)
print "\tSource Widget:", event.source()
print "\tTarget Widget:", self
if event.mimeData().hasFormat('text/plain'):
print "\tMime text:", event.mimeData().text()
}}}
!!!Events:
[[QWidget|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html]] drag/drop //event-related// methods:
*[[dragEnterEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.dragEnterEvent]] - Receives [[QDragEnterEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QDragEnterEvent.html]]
*[[dragMoveEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.dragMoveEvent]] - Receives [[QDragMoveEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QDragMoveEvent.html]]
*[[dragLeaveEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.dragLeaveEvent]] - Receives [[QDragLeaveEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QDragLeaveEvent.html]]
*[[dropEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.dropEvent]] - Receives [[QDropEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QDropEvent.html]]
Event Class Hierarchy:
*[[QDragLeaveEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QDragLeaveEvent.html]] - provides an event that is sent to a widget when a drag and drop action leaves it.
*[[QDropEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QDropEvent.html]] - provides an event which is sent when a drag and drop action is completed.
**[[QDragMoveEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QDragMoveEvent.html]] - provides an event which is sent while a drag and drop action is in progress.
***[[DragEnterEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QDragEnterEvent.html]] - provides an event which is sent to a widget when a drag and drop action enters it.
!!!Data:
*[[QMimeData|http://srinikom.github.io/pyside-docs/PySide/QtCore/QMimeData.html]] - Info about the [[MIME|http://en.wikipedia.org/wiki/MIME]] type.
*[[QtCore.Qt.DropAction|http://srinikom.github.io/pyside-docs/PySide/QtCore/Qt.html?highlight=pyside.qtcore.qt.dropaction#PySide.QtCore.PySide.QtCore.Qt.DropAction]] - used in the {{{setDropAction}}} method of the {{{QDropEvent}}} passed to a {{{QWidget}}}s {{{dropEvent}}} to control what happens to the data when dropped.
!!!Drag & Drop related methods
[[QWidget|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html]] drop related methods:
*[[acceptDrops|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.acceptDrops]] - This property holds whether drop events are enabled for this widget.
*[[setAcceptDrops|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.setAcceptDrops]] - Setting this property to true announces to the system that this widget may be able to accept drop events.
Other widgets support other drop actions. For example, the below [[QListWidget|http://srinikom.github.io/pyside-docs/PySide/QtGui/QListWidget.html]] inherits from [[QAbstractItemView|http://srinikom.github.io/pyside-docs/PySide/QtGui/QAbstractItemView.html]], which has its own set of drag methods:
*[[defaultDropAction|http://srinikom.github.io/pyside-docs/PySide/QtGui/QAbstractItemView.html#PySide.QtGui.PySide.QtGui.QAbstractItemView.defaultDropAction]]
*[[dropIndicatorPosition|http://srinikom.github.io/pyside-docs/PySide/QtGui/QAbstractItemView.html#PySide.QtGui.PySide.QtGui.QAbstractItemView.dropIndicatorPosition]]
*[[dragDropMode|http://srinikom.github.io/pyside-docs/PySide/QtGui/QAbstractItemView.html#PySide.QtGui.PySide.QtGui.QAbstractItemView.dragDropMode]]
*[[dragDropOverwriteMode|http://srinikom.github.io/pyside-docs/PySide/QtGui/QAbstractItemView.html#PySide.QtGui.PySide.QtGui.QAbstractItemView.dragDropOverwriteMode]]
*[[dragEnabled|http://srinikom.github.io/pyside-docs/PySide/QtGui/QAbstractItemView.html#PySide.QtGui.PySide.QtGui.QAbstractItemView.dragEnabled]]
*[[setDefaultDropAction|http://srinikom.github.io/pyside-docs/PySide/QtGui/QAbstractItemView.html#PySide.QtGui.PySide.QtGui.QAbstractItemView.setDefaultDropAction]]
*[[setDragEnabled|http://srinikom.github.io/pyside-docs/PySide/QtGui/QAbstractItemView.html#PySide.QtGui.PySide.QtGui.QAbstractItemView.setDragEnabled]]
*[[setDragDropMode|http://srinikom.github.io/pyside-docs/PySide/QtGui/QAbstractItemView.html#PySide.QtGui.PySide.QtGui.QAbstractItemView.setDragDropMode]]
*[[setDragDropOverwriteMode|http://srinikom.github.io/pyside-docs/PySide/QtGui/QAbstractItemView.html#PySide.QtGui.PySide.QtGui.QAbstractItemView.setDragDropOverwriteMode]]
*[[setDragEnabled|http://srinikom.github.io/pyside-docs/PySide/QtGui/QAbstractItemView.html#PySide.QtGui.PySide.QtGui.QAbstractItemView.setDragEnabled]]
*[[setDropIndicatorShown|http://srinikom.github.io/pyside-docs/PySide/QtGui/QAbstractItemView.html#PySide.QtGui.PySide.QtGui.QAbstractItemView.setDropIndicatorShown]]
*[[startDrag|http://srinikom.github.io/pyside-docs/PySide/QtGui/QAbstractItemView.html#PySide.QtGui.PySide.QtGui.QAbstractItemView.startDrag]]
*[[showDropIndicator|http://srinikom.github.io/pyside-docs/PySide/QtGui/QAbstractItemView.html#PySide.QtGui.PySide.QtGui.QAbstractItemView.showDropIndicator]]
!!!Simple Example:
{{{QListWidget}}}s have their own special methods making d&d easy:
{{{
import PySide.QtGui
# then in some class method...
self.wid1 = QtGui.QListWidget()
self.wid2 = QtGui.QListWidget()
self.hbox = QHBoxLayout()
self.hbox.addWidget(self.myListWidget1)
self.hbox.addWidget(self.myListWidget2)
self.wid1.setAcceptDrops(True)
self.wid1.setDragEnabled(True)
self.wid2.setAcceptDrops(True)
self.wid2.setDragEnabled(True)
# Make this display big icons, rather than small ones:
self.wid2.setViewMode(QListWidget.IconMode)
# Create an icon:
myIcon = QtGui.QListWidgetItem(QtGui.QIcon('someIconA.png'), "My Icon A")
# Add it to the first widget:
self.wid1.insertItem(1, myIcon)
# Create icon and add to the second widget at the same time:
QtGui.QListWidgetItem(QtGui.QIcon("someIconB.png"), "My Icon B", self.wid2)
self.setLayout(self.hbox)
}}}
Now icons can be dragged and dropped between the two {{{QListWidget}}}s. Note that based on this example the icons are //duplicated//, the old one isn't removed.
!!!Example Moar:
If you're using the above example, you can replace the {{{QListWidget}}}s with this one: It will print out when the drag/drops are happening, and it will //move// the items rather than copy them:
{{{
import PySide.QtGui
from QtCore import Qt
class MyListWidget(QtGui.QListWidget):
"""
Create a custom widget that prints the drag/drop actions.
"""
def dropEvent(self, event):
print "DROP", type(event)
# Move the item to the new location. If this isn't set, a copy will be
# made. Also, if dragged onto itself, and the action is set to move,
# it will delete itself, so check for that to:
if event.source() != self:
event.setDropAction(Qt.MoveAction)
return QListWidget.dropEvent(self, event)
def dragEnterEvent(self, event):
print "DRAG Enter", type(event)
return QListWidget.dragEnterEvent(self, event)
def dragMoveEvent(self, event):
print "DRAG Move", type(event)
return QListWidget.dragMoveEvent(self, event)
def dragLeaveEvent(self, event):
# Called when the drag is canceled, like dragging outside the window.
print "DRAG Leave", type(event)
return QListWidget.dragLeaveEvent(self, event)
}}}
Modified example pulled from [[here|https://stackoverflow.com/questions/48103685/youtube-video-embedding-pyqt]]
{{{
# in addition to your other imports:
from PySide2 import QtWebEngineWidgets
# Then in your code:
widget_webView = QtWebEngineWidgets.QWebEngineView()
widget_webView.setUrl("https://www.youtube.com/watch?v=oHg5SJYRHA0")
self.layout.addWidget(widget_webView)
}}}
Docs for [[QWebEngineView|https://doc.qt.io/qtforpython/PySide2/QtWebEngineWidgets/QWebEngineView.html]]
!!!Widgets
[[QWidget|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#events]]s have many event methods that can be overridden. The event methods are passed some subclass of the [[QEvent|http://srinikom.github.io/pyside-docs/PySide/QtCore/QEvent.html]] class.
*[[event|http://srinikom.github.io/pyside-docs/PySide/QtCore/QObject.html#PySide.QtCore.PySide.QtCore.QObject.event]] - Receives one of the below [[events|http://srinikom.github.io/pyside-docs/PySide/QtCore/QEvent.html]]. Inherited from {{{QObject}}}, is called to before any other events. The event from this is passed to the next appropriate event.
*[[eventFilter|http://srinikom.github.io/pyside-docs/PySide/QtCore/QObject.html#PySide.QtCore.PySide.QtCore.QObject.eventFilter]] - Inherited from {{{QObject}}} :
*[[paintEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.paintEvent]] - Receives [[QPaintEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QPaintEvent.html]]
*[[resizeEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.resizeEvent]] - Receives [[QResizeEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QResizeEvent.html]]
*[[mousePressEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.mousePressEvent]] - Receives [[QMouseEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QMouseEvent.html]]
*[[mouseReleasEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.mouseReleaseEvent]] - Receives [[QMouseEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QMouseEvent.html]]
*[[mouseDoubleClickedEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.mouseDoubleClickEvent]] - Receives [[QMouseEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QMouseEvent.html]]
*[[mouseMoveEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.mouseMoveEvent]] - Receives [[QMouseEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QMouseEvent.html]]
*[[wheelEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.wheelEvent]] - Receives [[QWheelEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWheelEvent.html]]
*[[keyPressEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.keyPressEvent]] - Receives [[QKeyEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QKeyEvent.html]]
*[[keyReleaseEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.keyReleaseEvent]] - Receives [[QKeyEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QKeyEvent.html]]
*[[focusInEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.focusInEvent]] - Receives [[QFocusEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QFocusEvent.html]]
*[[focusOutEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.focusOutEvent]] - Receives [[QFocusEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QFocusEvent.html]]
*[[enterEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.enterEvent]] - Receives [[QEvent|http://srinikom.github.io/pyside-docs/PySide/QtCore/QEvent.html]]
*[[leaveEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.leaveEvent]] - Receives [[QEvent|http://srinikom.github.io/pyside-docs/PySide/QtCore/QEvent.html]]
*[[moveEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.moveEvent]] - Receives [[QMoveEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QMoveEvent.html]]
*[[closeEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.closeEvent]] - Receives [[QCloseEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QCloseEvent.html]]
*[[dragEnterEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.dragEnterEvent]] - Receives [[QDragEnterEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QDragEnterEvent.html]]
*[[dragMoveEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.dragMoveEvent]] - Receives [[QDragMoveEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QDragMoveEvent.html]]
*[[dragLeaveEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.dragLeaveEvent]] - Receives [[QDragLeaveEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QDragLeaveEvent.html]]
*[[dropEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.dropEvent]] - Receives [[QDropEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QDropEvent.html]]
*[[showEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.showEvent]] - Receives [[QShowEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QShowEvent.html]]
*[[hideEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.hideEvent]] - Receives [[QHideEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QHideEvent.html]]
*[[changeEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.changeEvent]] - Receives [[QEvent|http://srinikom.github.io/pyside-docs/PySide/QtCore/QEvent.html]]
!!!Events
*[[QEvent|http://srinikom.github.io/pyside-docs/PySide/QtCore/QEvent.html]] - provides an event that is generated when a {{{QtGui.QAction}}} is added, removed, or changed.
**[[QAccessibleEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QAccessibleEvent.html]] - used to query addition accessibility information about complex widgets.
**[[QActionEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QActionEvent.html]]
**[[QChildEvent|http://srinikom.github.io/pyside-docs/PySide/QtCore/QChildEvent.html]] - contains event parameters for child object events.
**[[QClipboardEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QClipboardEvent.html]]
**[[QCloseEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QCloseEvent.html]] - contains parameters that describe a close event.
**[[QDragLeaveEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QDragLeaveEvent.html]] - provides an event that is sent to a widget when a drag and drop action leaves it.
**[[QDropEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QDropEvent.html]] - provides an event which is sent when a drag and drop action is completed.
***[[QDragMoveEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QDragMoveEvent.html]] - provides an event which is sent while a drag and drop action is in progress.
****[[DragEnterEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QDragEnterEvent.html]] - provides an event which is sent to a widget when a drag and drop action enters it.
**[[QDynamicPropertyChangeEvent|http://srinikom.github.io/pyside-docs/PySide/QtCore/QDynamicPropertyChangeEvent.html]] - contains event parameters for dynamic property change events.
**[[QFileOpenEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QFileOpenEvent.html]] - provides an event that will be sent when there is a request to open a file or a URL.
**[[QFocusEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QFocusEvent.html]] - contains event parameters for widget focus events.
**[[QGraphicsSceneEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsSceneEvent.html]] - provides a base class for all graphics view related events.
***[[QGraphicsSceneContextMenuEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsSceneContextMenuEvent.html]] - provides context menu events in the graphics view framework.
***[[QGraphicsSceneDragDropEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsSceneDragDropEvent.html]] - provides events for drag and drop in the graphics view framework.
***[[QGraphicsSceneHelpEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsSceneHelpEvent.html]] - provides events when a tooltip is requested.
***[[QGraphicsSceneHoverEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsSceneHoverEvent.html]] - provides hover events in the graphics view framework.
***[[QGraphicsSceneMouseEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsSceneMouseEvent.html]] - provides mouse events in the graphics view framework.
***[[QGraphicsSceneMoveEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsSceneMoveEvent.html]] - provides events for widget moving in the graphics view framework.
***[[QGraphicsSceneResizeEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsSceneResizeEvent.html]] - provides events for widget resizing in the graphics view framework.
***[[QGraphicsSceneWheelEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsSceneWheelEvent.html]] - provides wheel events in the graphics view framework.
**[[QGestureEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGestureEvent.html]] - provides the description of triggered gestures.
**[[QHelpEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QHelpEvent.html]] - provides an event that is used to request helpful information about a particular point in a widget.
**[[QHideEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QHideEvent.html]] - provides an event which is sent after a widget is hidden.
**[[QHoverEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QHoverEvent.html]] - contains parameters that describe a mouse event.
**[[QIconDragEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QIconDragEvent.html]] - indicates that a main icon drag has begun.
**[[QInputEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QInputEvent.html]] - the base class for events that describe user input.
***[[QContextMenuEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QContextMenuEvent.html]] - contains parameters that describe a context menu event.
***[[QKeyEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QKeyEvent.html]] - describes a key event.
***[[QMouseEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QMouseEvent.html]] - contains parameters that describe a mouse event.
***[[QTabletEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QTabletEvent.html]] - contains parameters that describe a Tablet event.
***[[QTouchEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QTouchEvent.html]] - contains parameters that describe a touch event.
***[[QWheelEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWheelEvent.html]] - contains parameters that describe a wheel event.
**[[QInputMethod|http://srinikom.github.io/pyside-docs/PySide/QtGui/QInputMethodEvent.html]] - provides parameters for input method events.
**[[QMoveEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QMoveEvent.html]] - contains event parameters for move events.
**[[QPaintEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QPaintEvent.html]] - contains event parameters for paint events.
**[[QResizeEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QResizeEvent.html]] - class contains event parameters for resize events.
**[[QShortcutEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QShortcutEvent.html]] - provides an event which is generated when the user presses a key combination.
**[[QShowEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QShowEvent.html]] - provides an event that is sent when a widget is shown.
**[[QStateMachine.SignalEvent|http://srinikom.github.io/pyside-docs/PySide/QtCore/QStateMachine.SignalEvent.html]] - class represents a Qt signal event.
**[[QStateMachine.WrappedEvent|http://srinikom.github.io/pyside-docs/PySide/QtCore/QStateMachine.WrappedEvent.html]] - holds a clone of an event associated with a {{{QtCore.QObject}}}.
**[[QStatusTipEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QStatusTipEvent.html]] - provides an event that is used to show messages in a status bar.
**[[QTimerEvent|http://srinikom.github.io/pyside-docs/PySide/QtCore/QTimerEvent.html]] - contains parameters that describe a timer event.
**[[QToolBarChangeEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QToolBarChangeEvent.html]] - provides an event that is sent whenever a the toolbar button is clicked on Mac OS X.
**[[QWhatsThisClickedEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWhatsThisClickedEvent.html]] - provides an event that can be used to handle hyperlinks in a “What’s This?” text.
**[[QWindowStateChangeEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWindowStateChangeEvent.html]] - provides the window state before a window state change.
----
<<<
From "~PySide Gui Application Development":
Qt offers 5 methods to do event processing:
*Re-implementing a specific event handler like {{{keyPressedEvent()}}}, {{{paintEvent()}}}.
*Re-implementing the {{{QObject.event()}}} class
*Installing an event filter on a single {{{Qobject}}}.
*Installing an event filter on the {{{QApplication}}} object.
*Subclassing {{{QApplication}}} and re-implementing {{{notify()}}}.
<<<
Make the correct type of validator and assign it:
{{{
self.widget_exportOnFrame = QtWidgets.QLineEdit()
self.layout_exporTypeOptions.addWidget(self.widget_exportOnFrame)
validator = QtGui.QIntValidator()
self.widget_exportOnFrame.setValidator(validator)
}}}
* [[QValidator|https://srinikom.github.io/pyside-docs/PySide/QtGui/QValidator.html]]
**[[QIntValidator|https://srinikom.github.io/pyside-docs/PySide/QtGui/QIntValidator.html]]
**[[QDoubleValidator|https://srinikom.github.io/pyside-docs/PySide/QtGui/QDoubleValidator.html]]
**[[QRegExpressionValidator|https://srinikom.github.io/pyside-docs/PySide/QtGui/QRegExpValidator.html]]
You can use the {{{setBottom}}} and {{{setTop}}} to define a numeric range for {{{QIntValidator}}} and {{{QDoubleValidator}}}.
----
Also see:
* [[PySide : Displaying Text]]
I ran into an issue where I had a custom {{{QSpinBox}}} created: When I clicked in it, I wanted to trigger a {{{QMouseEvent}}} on the parental {{{QWidget}}}. However, clicking //in// it triggers a {{{focusInEvent}}}, not a {{{mousePressEvent}}}. The {{{mousePressEvent}}} would only trigger if I clicked the one-pixel-wide border around it.
The below example shows how you can override the {{{focusInEvent}}}, make your own {{{QMouseEvent}}} inside it, and then pass that to the parental {{{QWidget}}} for execution.
{{{
from PySide.QtCore import QEvent, Qt
from PySide.QtGui import QApplication, QSpinBox, QMouseEvent
class SpinBox(QSpinBox):
def focusInEvent(self):
super(SpinBox, self).focusInEvent(event)
# Create our QMouseEvent:
eventType = QEvent.MouseButtonPress
cursor = self.parentWidget().cursor()
globalPos = cursor.pos()
pos = self.mapFromGlobal(globalPos)
buttons = QApplication.mouseButtons()
button = Qt.MouseButton(buttons)
modifiers = QApplication.keyboardModifiers()
mouseEvent = QMouseEvent(eventType, pos, globalPos, button, buttons, modifiers)
# Now trigger the parent widget's mousePressEvent
self.parentWidget().mousePressEvent(mouseEvent)
}}}
@@Update@@
Note, instead of the below {{{deleteItem}}} function, just {{{widget.close()}}}:
[[QWidget.close|https://doc.qt.io/qtforpython-5.12/PySide2/QtWidgets/QWidget.html#PySide2.QtWidgets.PySide2.QtWidgets.QWidget.close]] docs.
The widget needs to have this set first though, for it to delete on close, instead of just 'hiding' it:
{{{
widget.setAttribute(QtCore.Qt.WA_DeleteOnClose)
}}}
The {{{close()}}} method seems to work fine, and I didn't know about it (+{{{WA_DeleteOnClose}}}) at the time of authoring the lower code.
----
I'm not sure why this seems to be so hard in ~PySide: It seems like one of those things that should be easy and built-in, but I (and what appears to be half of the internet) seem to struggle with it. Here's a solution I came up with, based on a post I found [[here|http://josbalcaen.com/maya-python-pyqt-delete-all-widgets-in-a-layout/#comment-86120]].
It should be noted that if you're deleting UI elements and rebuilding them, the initial item you call deleteItem on should be a widget, not a layout: If you delete\rebuild a layout using this method, you can run into refresh issues. While if you delete\rebuild a widget hierarchy, it seems to 'just work'. Because of this I will often create a dummy parental widget that everything needing 'rebuilt' is a child of to support this.
{{{
from PySide import QtGui, QtCore
def deleteItem(item):
"""
Main entry point to 'really delete' PySide items. Not sure why this is normally
so hard to do.
Delete the passed in item, and all child items, whether widgets or layouts.
item : Either QWidget, or QLayout.
"""
if isinstance(item, QtGui.QWidget):
deleteWidget(item)
elif isinstance(item, QtGui.QLayout):
deleteLayout(item)
elif isinstance(item, (QtGui.QLayoutItem, QtGui.QWidgetItem)):
deleteLayoutItem(item)
else:
unreal.log_warning("Don't know how to delete: %s"%item)
def deleteLayoutItem(item):
"""
Delete the child of the provided LayoutItem. QLayoutItem, andit's subclass
QWidgetItem aren't subclasses of QWidget or QLayout, but I've seen them show
up in the child list.
Parameters:
item : QtGui.QLayoutItem or (subclass) QtGui.QWidgetItem
"""
if item.widget():
deleteWidget(item.widget())
if item.layout():
deleteLayout(item.layout())
def deleteLayout(layout):
"""
For the given layout instance, delete all child widgets and layouts
"""
try:
while layout.count():
child = layout.takeAt(0)
if child.widget() is not None:
deleteWidget(child.widget())
elif child.layout() is not None:
deleteLayout(child.layout())
elif isinstance(child, (QtGui.QLayoutItem, QtGui.QWidgetItem)):
deleteLayoutItem(child)
#print("DELETING layout: %s"%layout)
layout.deleteLater()
except:
pass
def deleteWidget(widget):
"""
Delete this widget, and any child widget\layouts.
"""
for child in widget.children():
if isinstance(child, QtGui.QWidget):
deleteWidget(child)
elif isinstance(child, QtGui.QLayout):
deleteLayout(child)
elif isinstance(child, QtCore.QObject):
#print("DELETING object: %s"%child)
child.deleteLater()
elif isinstance(child, (QtGui.QLayoutItem, QtGui.QWidgetItem)):
deleteLayoutItem(child)
#print("DELETING widget: %s"%widget)
widget.deleteLater()
}}}
Say, you want to dim one out in your window:
{{{
myWidget.setEnabled(False)
}}}
You can use the {{{QWidget}}}'s {{{activateWindow}}} method: This will force focus to that window/widget, which is sometimes needed for correct hotkey usage.
https://doc.qt.io/qtforpython-5/PySide2/QtWidgets/QSplitter.html
Actually not a layout, but a widget. Has adjustable slider in the middle.
The below overridden ~QWidget [[resizeEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.resizeEvent]] method can be used to keep a widget (or window) square regardless of how it is resized.
{{{
def resizeEvent(self, event):
# Create a square base size of 10x10 and scale it to the new size
# maintaining aspect ratio.
new_size = QtCore.QSize(10, 10)
new_size.scale(event.size(), QtCore.Qt.KeepAspectRatio)
self.resize(new_size)
}}}
From [[this thread|http://stackoverflow.com/questions/11008140/pyqt-custom-widget-fixed-as-square]].
Note, that changing the size to be non-square can send it into an endless loop.
I read a good descriptions in Maya's ~PySide docs:
<<<
In Qt a layout (i.e. a {{{QLayout}}} or something derived from it) is not a widget. It is attached to a widget to control the positioning of that widget's children but is not itself a child of the widget and does not appear in the widget hierarchy.
<<<
Layouts can:
* Contain multiple child widgets.
* Contain other layouts.
Widgets can:
* Contain multiple child widgets.
* Attach a single layout.
Visual reference of [[Layout Management|http://doc.qt.io/qt-5/layout.html]]
!!!Class Hierarchy:
All live in the [[QtGui|http://srinikom.github.io/pyside-docs/PySide/QtGui/index.html]] module:
*[[QLayoutItem|http://srinikom.github.io/pyside-docs/PySide/QtGui/QLayoutItem.html]] - Abstract item that a {{{QLayout}}} manipulates.
**[[QLayout|http://srinikom.github.io/pyside-docs/PySide/QtGui/QLayout.html]] - Also inherits from [[QObject|http://srinikom.github.io/pyside-docs/PySide/QtCore/QObject.html]] - base class of geometry managers.
***[[QBoxLayout|http://srinikom.github.io/pyside-docs/PySide/QtGui/QBoxLayout.html]] - lines up child widgets horizontally or vertically
****[[QHBoxLayout|http://srinikom.github.io/pyside-docs/PySide/QtGui/QHBoxLayout.html]] - construct horizontal box layout objects
****[[QVBoxLayout|http://srinikom.github.io/pyside-docs/PySide/QtGui/QVBoxLayout.html]] - lines up widgets vertically
***[[QFormLayout|http://srinikom.github.io/pyside-docs/PySide/QtGui/QFormLayout.html]] - manages forms of input widgets and their associated labels.
***[[QGridLayout|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGridLayout.html]] - lays out widgets in a grid
***[[QStackedLayout|http://srinikom.github.io/pyside-docs/PySide/QtGui/QStackedLayout.html]] - provides a stack of widgets where only one widget is visible at a time.
**[[QSpacerItem|http://srinikom.github.io/pyside-docs/PySide/QtGui/QSpacerItem.html]] - Provides blank space in a layout, what is inserted when the a 'spacing' or 'stretch' method is called to in a layout.
**[[QWidgetItem|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidgetItem.html]] - A layout item that represents a widget
!!!Widget Methods:
*{{{setParent}}} : This can parent a widget to another widget, outside a layout manager.
*{{{children}}} : Returns list of children.
!!!Common Layout Methods:
Listed in hierarchy inheritance order:
!!!!~QLayoutItem:
*{{{alignment()}}} : Returns alignment of this item.
*{{{geometry()}}} : Returns [[QRect|http://srinikom.github.io/pyside-docs/PySide/QtCore/QRect.html]]
*{{{layout()}}} : If this is a layout, returns a [[QLayout|http://srinikom.github.io/pyside-docs/PySide/QtGui/QLayout.html]], else zero.
*{{{sizeHint()}}} : Implemented in subclasses to return the preferred size of this item.
*{{{widget()}}} : If this is a widget, returns a [[QWidget|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html]], else zero.
!!!!~QLayout:
*{{{SizeConstraint()}}} : Used for setting the size of the layout, based on the [[constants|http://srinikom.github.io/pyside-docs/PySide/QtGui/QLayout.html#PySide.QtGui.PySide.QtGui.QLayout.SizeConstraint]]
*{{{addWidget()}}} : Add a widget to this layout.
*{{{addChildWidget()}}} : Called to from {{{addWidget()}}} : Not sure why you'd call it on your own?
*{{{addChildLayout()}}} : Called to from child subclassed {{{addLayout()}}} or {{{insertLayout()}}} : Not sure why you'd call it on your own?
*{{{contentsRect()}}} : Returns [[QRect|http://srinikom.github.io/pyside-docs/PySide/QtCore/QRect.html]]
*{{{count()}}} : Number of items in the layout.
*{{{parentWidget()}}} : Returns the parent [[QWidget|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html]] of this layout, or 0 if this layout isn't in a widget.
*{{{removeItem()}}} : Remove the given {{{QLayoutItem}}}
*{{{removeWidget()}}} : Remove the given {{{QWidget}}}
*{{{setAlignment()}}} : Set the alignment for the given {{{QWidget}}} or {{{QLayout}}}, based on the [[QtCore.Qt.Alignment|http://srinikom.github.io/pyside-docs/PySide/QtCore/Qt.html]] constants.
*{{{setMenuBar()}}} : Set the given {{{QWidget}}} as a menubar.
*{{{setSpacing()}}} : Sets spacing between widgets in the layout.
!!!!~QBoxLayout:
*{{{Direction}}} : Set the direction of the box layout via [[constants|http://srinikom.github.io/pyside-docs/PySide/QtGui/QBoxLayout.html#PySide.QtGui.PySide.QtGui.QBoxLayout.Direction]]
*{{{addLayout()}}} : Add the child layout.
*{{{addSpacerItem()}}} : Add a [[QSpacerItem|http://srinikom.github.io/pyside-docs/PySide/QtGui/QSpacerItem.html]] to the end of this layout.
*{{{addSpacing()}}} : Add a non-stretchable space.
*{{{addStretch()}}} : Add a stretchable space with a defined minimum size.
----
Also see:
*[[PySide : Widget & layout sizing policies]]
*[[PySide : Understanding widgets and layouts]]
This will create a pushbutton, set to the fixed size of the passed in image:
{{{
from PySide import QtGui
class ImageButton(QtGui.QPushButton):
def __init__(self, *args, **kwargs):
super(ImageButton, self).__init__(*args)
self.pixmap = QtGui.QPixmap.fromImage(QtGui.QImage(kwargs['image'])))
self.setIcon(self.pixmap)
self.setFixedSize(self.pixmap.size())
self.setIconSize(self.pixmap.size())
def paintEvent(self, event):
painter = QtGui.QPainter(self)
painter.drawPixmap(event.rect(), self.pixmap)
super(ImageButton, self).paintEvent(event)
}}}
{{{
but = ImageButton(image="full path to image")
}}}
The below example code shows how to create a simple widget (green box) that can be clicked & dragged around. This is a modified version of the very helpful tutorial I found:
http://stackoverflow.com/questions/12219727/dragging-moving-a-qpushbutton-in-pyqt
{{{
class MoveWidget(QtGui.QWidget):
"""
Create a simple green box widget that can be moved around its parent.
"""
def __init__(self, parent=None, limitX=False, limitY=False):
"""
Parameters:
parent : None\QWidget : Default None : The parent of this widget. If not
set here, will need to be parented later.
limitX, limitY : bool : Default False : Should the motion be limited on a
given axis? Makes it behave more like a slider.
"""
super(MoveWidget, self).__init__(parent=parent)
self.limitX = limitX
self.limitY = limitY
def paintEvent(self, event):
"""
Create a green square to move around:
"""
super(MoveWidget, self).paintEvent(event)
self.resize(64,64)
# http://srinikom.github.io/pyside-docs/PySide/QtGui/QPainter.html
qp = QtGui.QPainter(self)
qp.fillRect(self.rect(), QtGui.QColor(0,128,0,255))
def mousePressEvent(self, event):
"""
When the LMB is pressed, the press location is saved.
Method is http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.mousePressEvent
Passed in event is http://srinikom.github.io/pyside-docs/PySide/QtGui/QMouseEvent.html
"""
self.raise_() # Move on top of any other widgets
self.mousePressGlobPos = None
if event.button() == QtCore.Qt.LeftButton:
self.mousePressGlobPos = event.globalPos() # Qpoint
super(MoveWidget, self).mousePressEvent(event)
def mouseMoveEvent(self, event):
"""
When the mouse is moved, and the LMB is pressed, the location of the
widget is updated.
Method is http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.mouseMoveEvent
Passed in event is http://srinikom.github.io/pyside-docs/PySide/QtGui/QMouseEvent.html
"""
if event.buttons() == QtCore.Qt.LeftButton:
# Adjust offset from clicked point to origin of widget
globalPos = event.globalPos() # QPoint
# This is the delta from position defined in mousePressEvent:
delta = globalPos - self.mousePressGlobPos # QPoint
# http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.pos
# http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.mapToGlobal
localPos = self.pos() # QPoint
currPos = self.mapToGlobal(localPos) # QPoint
# http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.mapFromGlobal
newPos = self.mapFromGlobal(currPos + delta)
if self.limitX:
newPos = QtCore.QPoint(localPos.x(), newPos.y())
if self.limitY:
newPos = QtCore.QPoint(newPos.x(), localPos.y())
self.move(newPos)
self.mousePressGlobPos = globalPos
super(MoveWidget, self).mouseMoveEvent(event)
}}}
Then later in some parent window/widget. Note this //isn't// part of a layout manager: It's added directly to some parental widget:
{{{
# Limit the Y axis: Can only slide left-right :
moveWid = MoveWidget(parent=self, limitY=True)
# Set a default location
moveWid.move(64,64)
}}}
I always forget all this. Cheat sheet:
----
Inheritance:
* [[QAbstractButton|https://doc.qt.io/qtforpython/PySide2/QtWidgets/QAbstractButton.html]]
** [[QCheckBox|https://doc.qt.io/qtforpython/PySide2/QtWidgets/QCheckBox.html]]
Methods:
* {{{setChecked}}} : bool : Set the checked state.
* {{{isChecked}}} : bool :Return if it is checked or not
* {{{checkState}}} : {{{PySide2.QtCore.Qt.CheckState}}} : Which is {{{Qt.Unchecked}}} 0, {{{Qt.PartiallyChecked}}} 1, {{{Qt.Checked}}} 2.
But remember, that [[PySide : QSettings]] will save bools as strings ({{{"true"}}} & {{{"false"}}}), bleh.
Signals:
* {{{stateChanged}}} : Emits (int) 0 for unchecked, 2 for checked.
* {{{clicked}}} (inherited)
* {{{pressed}}} (inherited)
* {{{released}}} (inherited)
* {{{toggled}}} (inherited)
https://doc.qt.io/qtforpython/PySide2/QtWidgets/QComboBox.html
Since I always forget how to do this:
{{{
myCb = QtWidgets.QComboBox()
for item in ["itemA", "itemB", "itemC"]:
myCb.addItem(item)
myCb.setCurrentIndex(2)
myCb.currentIndexChanged.connect(myCallback)
}}}
To get the text of the current item:
{{{
cbText = myCb.itemText(myCb.currentIndex())
# OR
cbText = myCb.currentText()
}}}
Because I always forget this stuff
https://doc.qt.io/qtforpython/PySide2/QtWidgets/QFrame.html
A lot of stuff inherits from QFrame:
* scrollers, text fields \ labels, graphics, lists, splitters, tables, tool boxes, tree views, etc.
{{{
myFrame = QtFrame()
myFrame.setFrameStyle(QFrame.Panel | QFrame.Raised)
myFrame.setLineWidth(2)
}}}
See more on the frame styles here:
https://doc.qt.io/qtforpython/PySide2/QtWidgets/QFrame.html#detailed-description
These items are part of the [[Graphics View Framework|http://qt-project.org/doc/qt-4.8/graphicsview.html]]
Widget:
*[[QWidget|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html]] - Inherits from [[QObject|http://srinikom.github.io/pyside-docs/PySide/QtCore/QObject.html]] & [[QPaintDevice|http://srinikom.github.io/pyside-docs/PySide/QtGui/QPaintDevice.html]]
**[[QFrame|http://srinikom.github.io/pyside-docs/PySide/QtGui/QFrame.html]]
***[[QAbstractScrollArea|http://srinikom.github.io/pyside-docs/PySide/QtGui/QAbstractScrollArea.html]]
****[[QGraphicsView|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsView.html]] - Creates a widget for displaying the contents of a graphics scene:
Scene:
*[[QGraphicsScene|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsScene.html]] - Provides a surfaces for managing a large number of 2d graphic items, is added to {{{QGraphicsView}}} - Inherits from [[QObject|http://srinikom.github.io/pyside-docs/PySide/QtCore/QObject.html]].
----
Items:
*[[QGraphicsItem|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsItem.html]] - the base class for all graphical items added to a {{{QGraphicsScene}}}.
**[[QGraphicsItemGroup|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsItemGroup.html]] - provides a container that treats a group of items as a single item
**[[QGraphicsPixmapItem|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsPixmapItem.html]] - Provides a pixmap item
**[[QGraphicsLineItem|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsLineItem.html]] - Provides a line item
**[[QAbstractGraphicsShapeItem|http://srinikom.github.io/pyside-docs/PySide/QtGui/QAbstractGraphicsShapeItem.html]] - provides a common base for all path items
***[[QGraphicsSimpleTextItem|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsSimpleTextItem.html]] - provides a simple text path item
***[[QGraphicsPolygonItem|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsPolygonItem.html]] - provides a polygon item
***[[QGraphicsEllipseItem|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsEllipseItem.html]] - provides an ellipse item
***[[QGraphicsRectItem|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsRectItem.html]] - provides a rectangle item
***[[QGraphicsPathItem|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsPathItem.html]] - provides a path item
**[[QGraphicsObject|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsObject.html]] - provides a base class for all graphics items that require signals, slots and properties. Also inherits from [[QObject|http://srinikom.github.io/pyside-docs/PySide/QtCore/QObject.html]]
***[[QGraphicsSvgItem|http://srinikom.github.io/pyside-docs/PySide/QtSvg/QGraphicsSvgItem.html]] - can be used to render the contents of SVG files
***[[QGraphicsTextItem|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsTextItem.html]] - provides an item that can display formatted text
Effects:
*[[QGraphicsEffect|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsEffect.html]] - The base class for all graphics effects - Inherits from [[QObject|http://srinikom.github.io/pyside-docs/PySide/QtCore/QObject.html]]
**[[QGraphicsOpacityEffect|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsOpacityEffect.html]] - This effect is useful for making the source semi-transparent, similar to a fade-in/fade-out sequence.
**[[QGraphicsBlurEffect|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsBlurEffect.html]] - This effect is useful for reducing details, such as when the source loses focus and you want to draw attention to other elements.
**[[QGraphicsColorizeEffect|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsColorizeEffect.html]] - provides a colorize effect.
**[[QGraphicsDropShadowEffect|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsDropShadowEffect.html]] - renders the source with a drop shadow
Layouts:
*[[QGraphicsLayoutItem|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsLayoutItem.html]] - can be inherited to allow your custom items to be managed by layouts
**[[QGraphicsLayout|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsLayout.html]] - provides the base class for all layouts in Graphics View
***[[QGraphicsLinearLayout|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsLinearLayout.html]] - provides a horizontal or vertical layout
***[[QGraphicsGridLayout|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsGridLayout.html]] - provides a grid layout
***[[QGraphicsAnchorLayout|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsAnchorLayout.html]] - provides a layout where one can anchor widgets together
**[[QGraphicsWidget|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsWidget.html]] - The base class for all widget items in a {{{QGraphicsScene}}}. Also inherits from {{{QGraphicsObject}}}.
***[[QGraphicsProxyWidget|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsProxyWidget.html]] - Provides a proxy layer for embedding a {{{QWidget}}} in a {{{QGraphicsScene}}}
***[[QGraphicsWebView|http://srinikom.github.io/pyside-docs/PySide/QtWebKit/QGraphicsWebView.html]] - allows Web content to be added to a {{{GraphicsView}}}
Events:
*[[QGraphicsSceneEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsSceneEvent.html]] - provides a base class for all graphics view related events - Inherits from [[QEvent|http://srinikom.github.io/pyside-docs/PySide/QtCore/QEvent.html]]
**[[QGraphicsSceneContextMenuEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsSceneContextMenuEvent.html]] - provides context menu events in the graphics view framework.
**[[QGraphicsSceneDragDropEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsSceneDragDropEvent.html]] - provides events for drag and drop in the graphics view framework.
**[[QGraphicsSceneHelpEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsSceneHelpEvent.html]] - provides events when a tooltip is requested.
**[[QGraphicsSceneHoverEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsSceneHoverEvent.html]] - provides hover events in the graphics view framework.
**[[QGraphicsSceneMouseEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsSceneMouseEvent.html]] - provides mouse events in the graphics view framework.
**[[QGraphicsSceneMoveEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsSceneMoveEvent.html]] - provides events for widget moving in the graphics view framework.
**[[QGraphicsSceneResizeEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsSceneResizeEvent.html]] - provides events for widget resizing in the graphics view framework.
**[[QGraphicsSceneWheelEvent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsSceneWheelEvent.html]] - provides wheel events in the graphics view framework.
Other:
*[[QGraphicsAnchor|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsAnchor.html]] - represents an anchor between two items in a {{{QGraphicsAnchorLayout}}}.
*[[QGraphicsItemAnimation|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsItemAnimation.html]] - provides simple animation support for {{{QGraphicsItem}}}.
*[[QGraphicsTransform|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsTransform.html]] - an abstract base class for building advanced transformations on {{{QGraphicsItems}}} - Inherits from [[QObject|http://srinikom.github.io/pyside-docs/PySide/QtCore/QObject.html]]
**[[QGraphicsRotation|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsRotation.html]] - provides a rotation transformation around a given axis.
**[[QGraphicsScale|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGraphicsScale.html]] - provides a scale transformation.
Super simple example inside some window class:
{{{
from PySide.QtGui import QVBoxLayout, QGraphicsView, QGraphicsScene, QGraphicsEllipseItem
def createLayout(self):
self.myLayout = QVBoxLayout()
self.myGraphicsView = QGraphicsView()
self.myGraphicsScene = QGraphicsScene()
self.myGraphicsItem = QGraphicsEllipseItem(-200, -200, 400, 400)
self.myGraphicsScene.addItem(self.myGraphicsItem)
self.myGraphicsView.setScene(self.myGraphicsScene)
self.myLayout.addWidget(self.myGraphicsView)
self.setLayout(self.myLayout)
}}}
Just as a reminder:
https://doc.qt.io/qtforpython/PySide2/QtWidgets/QGridLayout.html
rows/columns are 1-index based, and coordinates are (Y,X).
{{{
layout_grid = QtWidgets.QGridLayout()
layout_grid.addWidget(widget_someWid, aRowY, aColumnX)
}}}
You can also have the span multiple rows/columns. Here's an example of it stretching multiple rows
{{{
layout_grid.addWidget(widget_someWid, startRowY, startColumnX, endRowY/rowHeight, endColumnX, QtCore.Qt.AlignTop)
}}}
So if you wanted a button in the 6th row to start in the 3nd column (col 2), be 1 row high, and stretch to the 4th column:
{{{
layout_grid.addWidget(widget_someWid, 6, 2, 1, 4))
}}}
I've found if I don't include the 'alignment', they won't show up correctly. It should be noted you can include the alignment at any time, to help 'center' things in the cels if needed.
"...performs low-level painting on widgets and other paint devices."
{{{QPainter}}} Docs:
*[[Main Docs|http://srinikom.github.io/pyside-docs/PySide/QtGui/QPainter.html]] ([[Qt|http://qt-project.org/doc/qt-4.8/qpainter.html]] version, in some cases has better imagery)
**[[Settings|http://srinikom.github.io/pyside-docs/PySide/QtGui/QPainter.html#settings]]
**[[Drawing|http://srinikom.github.io/pyside-docs/PySide/QtGui/QPainter.html#drawing]]
**[[Rendering Quality|http://srinikom.github.io/pyside-docs/PySide/QtGui/QPainter.html#rendering-quality]]
**[[Coordinate Transformations|http://srinikom.github.io/pyside-docs/PySide/QtGui/QPainter.html#coordinate-transformations]]
**[[Clipping|http://srinikom.github.io/pyside-docs/PySide/QtGui/QPainter.html#clipping]]
**[[Composition Modes|http://srinikom.github.io/pyside-docs/PySide/QtGui/QPainter.html#composition-modes]] - Used for compositing.
Other Docs:
* [[QGradient|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGradient.html]]
** [[QLinear Gradient|http://srinikom.github.io/pyside-docs/PySide/QtGui/QLinearGradient.html]]
** [[QRadialGradient|http://srinikom.github.io/pyside-docs/PySide/QtGui/QRadialGradient.html]]
** [[QConicalGradient|http://srinikom.github.io/pyside-docs/PySide/QtGui/QConicalGradient.html]]
* [[QBrush|http://srinikom.github.io/pyside-docs/PySide/QtGui/QBrush.html]] - Defines the fill pattern of shapes.
* [[QPen|http://srinikom.github.io/pyside-docs/PySide/QtGui/QPen.html]] - Defines how a {{{QtGui.QPainter}}} should draw lines and outlines of shapes.
* [[QColor|http://srinikom.github.io/pyside-docs/PySide/QtGui/QColor.html]] - Provides colors based on RGB, HSV or CMYK values
* [[QRect|http://srinikom.github.io/pyside-docs/PySide/QtCore/QRect.html]]
* [[QPoint|http://srinikom.github.io/pyside-docs/PySide/QtCore/QPoint.html]]
* [[QPointF|http://srinikom.github.io/pyside-docs/PySide/QtCore/QPointF.html]]
* [[QFont|http://srinikom.github.io/pyside-docs/PySide/QtGui/QFont.html]]
{{{
from PySide import QtGui, QtCore
from PySide.QtCore import Qt
class CustomWidget(QtGui.QWidget):
def paintEvent(self, event):
qp = QtGui.QPainter(self)
# Fill with a gradient:
gradient = QtGui.QLinearGradient(QtCore.QPointF(0, 0),
QtCore.QPointF(size.width(), size.height()))
gradient.setColorAt(0.0, Qt.red)
gradient.setColorAt(0.5, Qt.yellow)
gradient.setColorAt(1.0, Qt.blue)
qp.fillRect(self.rect(), gradient)
# Fill with a solid color (that can also have a pattern):
brush = QtGui.QBrush(Qt.red, Qt.CrossPattern)
qp.fillRect(self.rect(), brush)
# Draw some text in the middle:
qp.setPen(Qt.black)
font = QtGui.QFont('Serif', 7, QtGui.QFont.Light)
qp.setFont(font)
qp.drawText(self.rect(), Qt.AlignCenter, "My Text!")
# Draw a rectangle at a given location:
qp.setPen(Qt.white)
# or: color, thickness, style:
qp.setPen(Qt.white, 2, Qt.SolidLine)
qp.setBrush(Qt.yellow)
# or : Color, pattern:
qp.setBrush(Qt.yellow, Qt.CrossPattern)
qp.drawRect(32, 32, 64, 64)
}}}
I've also see it implemented this way:
{{{
def paintEvent(self, event):
qp = QtGui.QPainter()
qp.begin(self)
self.drawWidget(qp)
qp.end()
def drawWidget(self, qp):
# Implement QPainter drawing here...
}}}
{{{QSettings}}} are serialized preferences that can be hooked to a specific window name.
https://doc.qt.io/qtforpython/PySide2/QtCore/QSettings.html
On Windows, by default, they'll store in the registry using this method:
{{{
from PySide2 import QtCore
settings = QtCore.QSettings("Company Name", "WindowName")
settings.setValue("startingDir", fileDir)
val = settings.value("startingDir", "optionalDefault")
}}}
But you can also store them to any local file like this:
{{{
settingsPath = "c:/path/to/mySettings.ini"
settings = QtCore.QSettings(settingsPath, QtCore.QSettings.IniFormat)
}}}
Both the dir & the file will be auto created if they do not exist.
!Weirdness
It appears that {{{QSettings}}} doesn't maintain the type of the stored value:
{{{
from PySide2 import QtCore
settings = QtCore.QSettings("MyCompany", "superSettings")
settings.setValue("float2.2", 2.2)
settings.setValue("float1.0", 1.0)
settings.setValue("float0.0", 0.0)
settings.setValue("int1", 1)
settings.setValue("int0", 0)
settings.setValue("True", True)
settings.setValue("False", False)
settings.setValue("string", "word")
print "float 1.0:", settings.value("float1.0"), type(settings.value("float1.0"))
print "float 0.0:", settings.value("float0.0"), type(settings.value("float0.0"))
print "float 2.2", settings.value("float2.2"), type(settings.value("float2.2"))
print "int 1:", settings.value("int1"), type(settings.value("int1"))
print "int 0:", settings.value("int0"), type(settings.value("int0"))
print "bool True:", settings.value("True"), type(settings.value("True"))
print "bool False:", settings.value("False"), type(settings.value("False"))
print "string 'string':",settings.value("string"), type(settings.value("string"))
}}}
{{{
float 1.0: "1" <type 'unicode'>
float 0.0: None <type 'NoneType'>
float 2.2: "2.2" <type 'unicode'>
int 1: 1 <type 'long'>
int 0: None <type 'NoneType'>
bool True: "true" <type 'unicode'>
bool False: "false" <type 'unicode'>
string 'string': "word" <type 'unicode'>
}}}
* {{{float}}} of {{{1.0}}} are returned as {{{string}}} of {{{"1"}}}.
* {{{float}}} of {{{0.0}}} are returned as {{{NoneType}}} / {{{None}}}
* {{{float}}} of an arbitrary number ({{{2.2}}}) is reutned as {{{string}}} {{{"2.2"}}}.
* {{{int}}} of {{{1}}} are returned as long (so, still an {{{int}}} of {{{1}}}).
* {{{int}}} of {{{0}}} are returned as {{{NoneType}}} / {{{None}}}
* {{{bool}}} {{{True}}} is returned as {{{string}}} {{{"true"}}}.
* {{{bool}}} {{{False}}} is returned as {{{string}}} {{{"false"}}}.
* {{{string}}} is returned as {{{string}}}.
This makes things far more confusing than they should be when reloading prefs...
Since (from what I understand) ~QSettings are stored in the Windows registry, I wonder if this is actually a Windows issue? And would different values store on different OS's, based on how they store it?
Random notes:
* https://srinikom.github.io/pyside-docs/PySide/QtGui/QTableWidget.html
* https://srinikom.github.io/pyside-docs/PySide/QtGui/QTableWidgetItem.html
* https://srinikom.github.io/pyside-docs/PySide/QtGui/QHeaderView.html
Example Code.
This shows a rough outline of how to setup something that has three columns, with custom header names, how to fill the lower cells with normal, and custom items.
{{{
from PySide2 import QtWidgets, QtCore
myListOfStuff = [some big list of stuff]
widget_table = QtWidgets.QTableWidget(len(myListOfStuff)+1, 3 )
widget_table.setSelectionMode(QtWidgets.QAbstractItemView.SelectionMode.NoSelection)
layout_someParentLayout.addWidget(widget_table)
if widget_table:
# Setup our header row:
# Header row background color:
brush_bg = QtGui.QBrush()
brush_bg.setColor(QtGui.QColor(80,80,80))
brush_bg.setStyle(QtCore.Qt.BrushStyle.SolidPattern)
widget_lableA = QtWidgets.QTableWidgetItem("Attach Joint:")
widget_labelB = QtWidgets.QTableWidgetItem("Current Target:")
widget_lableC = QtWidgets.QTableWidgetItem("New Target:")
# Set alignment, and color on the main header:
for wid in (widget_lableA, widget_labelB, widget_lableC):
wid.setTextAlignment(QtCore.Qt.AlignCenter)
wid.setBackground(brush_bg)
# y,x
widget_table.setItem(0, 0, widget_lableA)
widget_table.setItem(0, 1, widget_labelB)
widget_table.setItem(0, 2, widget_lableC)
# Make the columns stretch to fit their content sizes:
header = widget_table.horizontalHeader()
for i in range(2):
header.setSectionResizeMode(i, QtWidgets.QHeaderView.ResizeToContents)
# Make the last column stretch:
header.setSectionResizeMode(2, QtWidgets.QHeaderView.Stretch)
#--------
# Fill in the lower data for each row/column...
for i,name in enumerate(myListOfStuff):
widget_thisLabel = QtWidgets.QTableWidgetItem(name)
widget_anotherLabel = QtWidgets.QTableWidgetItem("blargh")
widget_table.setItem(i+1, 0, widget_thisLabel)
widget_table.setItem(i+1, 1, widget_anotherLabel)
widget_listOfStuff = QtWidgets.QComboBox()
for item in ["list", "of", "stuff"]:
widget_listOfStuff.addItem(item)
# NO
# widget_table.setItem(i+1, 2, widget_listOfStuff)
# YES
widget_table.setCellWidget(i+1, 2, widget_listOfStuff)
}}}
Just some simple examples of how to implement
{{{
from PySide import QtCore, QtGui, QtUiTools
class MyWindow(QtGui.QWidget):
def __init__(self, parent=None):
super(MyWindow, self).__init__(parent)
# Get the widget from the loaded ui file
self.widget_ui = QtUiTools.QUiLoader().load("c:/path/to/my/uiFile.ui")
# Attach the widget to the parental UI widget
self.widget_ui.setParent(self)
# Set the ui's geometry to make it fit the parent:
self.widget_ui.setGeometry(0, 0, self.widget.width(), self.widget.height())
# Now, search for some sub-widget by name
self.widget_myWords = self.widget.findChild(QtGui.QLineEdit, "textBox_myWords")
}}}
The [[QApplicatin|http://srinikom.github.io/pyside-docs/PySide/QtGui/QApplication.html]] class can return a number of things about the current state of the scene. Most recently things I've used are:
* Mouse position
* Keyboard modifiers
* Finding which widget lives at a given position.
* many more...
This is how you can undo a size constraints, but Qt Doesn't export this macro to Python. So instead, this bitwise operator can be used.
* https://doc.qt.io/archives/qtforpython-5.12/PySide2/QtWidgets/QWidget.html#PySide2.QtWidgets.PySide2.QtWidgets.QWidget.setFixedSize
* https://riverbankcomputing.com/pipermail/pyqt/2015-April/035746.html
{{{
QWIDGETSIZE_MAX = ((1 << 24) - 1)
# Remove any previous myWidget.setMaximumHeight() calls:
myWidget.setMaximumHeight(QWIDGETSIZE_MAX)
}}}
[[QtWidget.adjustSize|https://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.adjustSize]] is the method. But I can't always get it to work predictably. More notes needed here.
I wanted to add a {{{QScrollArea}}} //around// a {{{QVboxLayout}}} and was having a hard time. Found a good tutorial here:
http://nealbuerger.com/2013/11/pyside-qvboxlayout-with-qscrollarea/
The issue is, you can't assign a layout directly to a {{{QScrollArea}}}: it wants a child //widget//. But you can assign a layout to a widget, so a "container widget" is created. The 'container widget' has a {{{QVBoxLayout}}} layout assigned, and then the container widget can be assigned to the {{{QScrollArea}}}. Magic!
{{{
from PySide.QtGui import QWidget, QVBoxLayout, QPushButton, QScrollArea
#Scroll Area Widget
widget_scroller= QScrollArea(self)
widget_scroller.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
widget_scroller.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
widget_scroller.setWidgetResizable(True) # Important for children to be correct size.
# layout_top is some already made layout that the high-level widget manages.
layout_top.addWidget(widget_scroller)
# Container widget:
widget_scrollContainer= QWidget(widget_scroller)
widget_scroller.setWidget(widget_scrollContainer)
# Layout for container widget
layout_scroller= QVBoxLayout()
widget_scrollContainer.setLayout(layout_scroller)
for i in range(8):
# Add some dummy widgets just to see stuff in there
layout_scroller.addWidget(QPushButton(self))
}}}
I should note that, even if you don't want to use a layout manager (like the {{{QVBoxLayout}}}) in the {{{QScrollArea}}}, and instead want to parent and manage {{{QWidget}}} (and its subclasses) directly, you //still// need to create the 'containerWidget', and parent your other {{{QWidgets}}} to it: If you don't, the scrollbars won't detect them, and you'll have a non-scrolling {{{QScrollArea}}} :(
{{{
from PySide import QtGui
butFont = QtGui.QFont()
butFont.setPixelSize(10) # or setPointSize
but = QtGui.QPushButton()
but.setFont(butFont)
}}}
This seems far more difficult than it should be, but it probably makes sense when authoring larger apps.
{{{
from PySide import QtGui
label = QtGui.QLabel()
pal = QtGui.QPalette()
textBrush = QtGui.QBrush(QtGui.QColor(0,0,0))
pal.setBrush(QtGui.QPalette.WindowText, textBrush)
label.setPalette(pal)
}}}
Docs:
*[[QWidget|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html]]
**[[QLabel|http://srinikom.github.io/pyside-docs/PySide/QtGui/QLabel.html]]
*[[QPalette|http://srinikom.github.io/pyside-docs/PySide/QtGui/QPalette.html]]
*[[QBrush|http://srinikom.github.io/pyside-docs/PySide/QtGui/QBrush.html]]
*[[QColor|http://srinikom.github.io/pyside-docs/PySide/QtGui/QColor.html]]
{{{
from PySide.QtGui import QPushButton
from PySide.QtCore import Qt
b = QPushButton("My Button")
# b.setAutoFillBackground(True) # Not needed?
p = b.palette()
p.setColor(b.backgroundRole(), Qt.green)
b.setPalette(p)
}}}
http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html
http://srinikom.github.io/pyside-docs/PySide/QtGui/QPalette.html
Docs:
* http://srinikom.github.io/pyside-docs/PySide/QtCore/Signal.html
* http://srinikom.github.io/pyside-docs/PySide/QtCore/Slot.html
Tutorials:
* https://qt-project.org/wiki/Signals_and_Slots_in_PySide
* http://zetcode.com/gui/pysidetutorial/eventsandsignals/
<<<
A signal is emitted when a particular event occurs. A slot can be any Python callable. A slot is called when a signal connected to it is emitted.
<<<
----
Create a custom signal:
{{{
from PySide import QtCore
# You can tell a signal what type of data to later emit if you like. In this case,
# it will emit some type of event. I'm told you add signals as the class level:
class MyClass(object)
sig = QtCore.Signal(str)
def __init__(self):
# bunch of code..., one of them makes a button, that calls to our own custom
# press event:
myButton = QtWidgets.QPushButton("Press me")
myButton.clicked.connect(self.customButPress)
def customButPress(self):
# now, we emit our own custom signal to the world!!!
self.sig.emit("special info!!!")
class SomeOtherThing(object):
# Some other class that builds a bunch of stuff...
def __init__(self):
# bunch of creation code then:
myClass = MyClass()
# NOW, we can connect the custom signal from MyClass to something in there:
myClass.sig.connect(self.doWork)
def doWork(self, *args):
# do custom work here, based on the signal emitted from MyClass
myData = args[0]
print(myData)
}}}
----
Signals can be emitted from a widget easily. Here's two different ways to do the same thing. {{{updateTime}}} is a custom method.
{{{
from PySide.QtCore QTimer, SIGNAL
# Inside some creation method...
self.timer = QTimer(self)
self.timer.timeout.connect(self.updateTime)
def updateTime(self):
# Here, we can find out which widget called to this method. Magic!
callingWidget = self.sender()
}}}
If you want to connect a signal passing a custom arg you can use either {{{lambda}}} or {{{functools.partial}}} to do so:
{{{
self.mywidget.widgetAction.connect(lambda: self.myMethod(someArg))
}}}
And older deprecated way of connecting signals: Don't do it this way, but shown for reference:
{{{
self.connect(self.timer, SIGNAL("timeout()"), self.updateTime)
}}}
{{{timeout}}} signal from [[QTimer|http://srinikom.github.io/pyside-docs/PySide/QtCore/QTimer.html]].
{{{connect}}} is inherited from [[QObject|http://srinikom.github.io/pyside-docs/PySide/QtCore/QObject.html]], and {{{self}}} is a parental window {{{QDialog}}}.
----
There are also:
{{{
QTCore.Slot
QTCore.SLOT
}}}
For ~PySide2
[[I'm told|https://forum.qt.io/topic/57675/which-file-formats-or-codecs-does-qmediaplayer-support]] on Windows, it supports anything Direct Show does. For a list:
https://msdn.microsoft.com/en-us/library/windows/desktop/dd407173%28v=vs.85%29.aspx
Also see:
* http://doc.qt.io/qt-5/qtmultimedia-windows.html
I seem to forget this stuff, so a scratchpad to remind me.
! Save settings
I often addd these to my window's __init__ method:
{{{
self.settings = QtCore.QSettings("myStudioName", MyWindow.name)
}}}
They can be accessed like a dict, and serialize to disk.
! Dynamical resize layouts when widgets are changed.
If you procedurally add or delete widgets from a layout, sometimes after the add/delete, the layout won't resize itself correctly. And you slowly go insane.
The solution is on the parental layout that has the dynamically added/removed child widgets/layouts, you need to do a:
{{{
myLayout.addStretch()
}}}
At the very end. This will help keep everything the right size as things are added and removed.
There's a gotcha though: If you build a window with hidden widgets and then show them, it's possible the layout won't expand correctly to hold them. To combat this, you should build all your widgets visible, and then hide them as needed after the window is created.
//However// : IT appears that if you dynamically add new widgets to a layout after the layout was created, the layout won't resize to fit them. I'm clearly doing something wrong, and right now have to rebuild the whole ui in the process to compensate.
! Copying/pasting data:
{{{
from PySide2 import QtGui
def copy(text):
QtGui.QClipboard().setText(text)
def paste():
return QtGui.QClipboard().text()
}}}
! Make a ~QWidget, like a ~QLineEdit non-editable (just display text)
{{{
QLineEdit.setReadOnly(True)
# If you want it to 'dim' in the process, which also makes it read only FYI:
QLineEdit.setEnabled(True)
}}}
! Add an annotation / tooltip to a widget:
{{{
myWidget.setToolTip("Tooltip here!")
}}}
! Set a widgets size:
{{{
myWidget.setFixedSize(x,y)
myWidget.setHeight(y)
myWidget.setWidth(x)
}}}
! Make a separator
{{{
from PySide2 import QtWidgets
class VSeparator(QtWidgets.QFrame):
def __init__(self, *args, **kwargs):
super(VSeparator, self).__init__(*args, **kwargs)
self.setFrameShape(QtWidgets.QFrame.VLine) # Or change to HLine for a horizontal separator
self.setFrameShadow(QtWidgets.QFrame.Sunken)
}}}
! Make empty space between widgets
{{{
from PySide2 import QtWidgets
class EmptySpace(QtWidgets.QFrame):
def __init__(self, width, *args, **kwargs):
super(EmptySpace, self).__init__(*args, **kwargs)
self.setFrameShape(QtWidgets.QFrame.NoFrame)
self.setFixedWidth(width)
}}}
----
! Make a frame with a label in it:
{{{
myLabel = QtWidgets.QLabel("Amazing Things Below!")
myLabel.setFrameStyle(QtWidgets.QFrame.Panel | QtWidgets.QFrame.Raised)
myLabel.setLineWidth(2)
myLabel.setFixedHeight(32)
myLayout.addWidget(myLabel )
}}}
! ~QRadioButton
Make a pair of radio buttons that only interact with each others, not any others in the window.
If you don't collect them in a ~QButtonGroup, then other ~QRadioButtons you make later will be included.
{{{
# Create a new button group parented to the current window. These can't be added to layouts,
# nor do they need to.
butGrpA = QtWidgets.QButtonGroup(self)
radA1 = QtWidgets.QRadioButton("A1")
radA1.setChecked(True)
radA2 = QtWidgets.QRadioButton("A2")
# Add buttons to both group, and parental layout:
myLayout.addWidget(radA1)
myLayout.addWidget(radA2)
butGrpA.addButton(self.radA1 , 1)
butGrpB.addButton(self.radA2 , 2)
# And connect the group to a callback.
# It passes the instance of the radioButon most recently clicked to it.
butGrpA.buttonClicked.connect(self.myRadioButtonCB)
# There doesn't seem to be a way to set the checked button via the group.
# you instead have to set the individual buttons check state:
radA1.setChecked(True)
# To query:
checkedButWidget = butGrpA.checkedButton() # would be radA1
}}}
A 'model' defines some type of data, and a 'view' displays it.
!Item Models
The back-end that stores the data (inherits from ~QObject)
* [[QAbstractItemModel|http://srinikom.github.io/pyside-docs/PySide/QtCore/QAbstractItemModel.html]] : Abstract superclass for all models.
** [[QFileSystemModel|http://srinikom.github.io/pyside-docs/PySide/QtGui/QFileSystemModel.html]] : provides a data model for the local filesystem, as used by {{{QTreeView}}}, and uses {{{QItemSelectionModel}}}.
** [[QStandardItemModel|http://srinikom.github.io/pyside-docs/PySide/QtGui/QStandardItemModel.html]] : provides a generic model for storing custom data, uses {{{QStandardItem}}}.
** [[QStringListModel|http://srinikom.github.io/pyside-docs/PySide/QtGui/QStringListModel.html]] : provides a model that supplies strings to views, as used by {{{QListView}}}.
** [[QAbstractTableModel|http://srinikom.github.io/pyside-docs/PySide/QtCore/QAbstractTableModel.html]] : provides an abstract model that can be subclassed to create table models.
*** Has several child classes all based around SQL.
** [[QDirModel|http://srinikom.github.io/pyside-docs/PySide/QtGui/QDirModel.html]] : provides a data model for the local filesystem
** [[QAbstractProxyModel|http://srinikom.github.io/pyside-docs/PySide/QtGui/QAbstractProxyModel.html]] : provides a base class for proxy item models that can do sorting, filtering or other data processing tasks.
*** [[QSortFilterProxyModel|http://srinikom.github.io/pyside-docs/PySide/QtGui/QSortFilterProxyModel.html]] : provides support for sorting and filtering data passed between another model and a view.
** [[QProxyModel|http://srinikom.github.io/pyside-docs/PySide/QtGui/QProxyModel.html]] : provides support for processing data passed between another model and a view.
** [[QHelpContentModel|http://srinikom.github.io/pyside-docs/PySide/QtHelp/QHelpContentModel.html]] : provides a model that supplies content to views.
** [[QAbstractListModel|http://srinikom.github.io/pyside-docs/PySide/QtCore/QAbstractListModel.html]] : provides an abstract model that can be subclassed to create one-dimensional list models.
*** Has child clases for Phonon and ~QHelpIndexModel
** [[QStringListModel|http://srinikom.github.io/pyside-docs/PySide/QtGui/QStringListModel.html]] : provides a model that supplies strings to views
!!Associated Items:
* [[QModelIndex|http://srinikom.github.io/pyside-docs/PySide/QtCore/QModelIndex.html]] : used to locate data in a data model, used by any subclass of {{{QAbstractItemModel}}}. Returned via {{{QAbstractItemModel.index(row, column)}}}
* [[QStandardItem|http://srinikom.github.io/pyside-docs/PySide/QtGui/QStandardItem.html]] : provides an item for use with the {{{QStandardItemModel}}} class.
!Item Views
The physical Widget that draws the UI elements (inherits from ~QWidget)
* [[QAbstractItemView|http://srinikom.github.io/pyside-docs/PySide/QtGui/QAbstractItemView.html]] : Abstract superclass for all views
** [[QTreeView|http://srinikom.github.io/pyside-docs/PySide/QtGui/QTreeView.html]] : provides a default model/view implementation of a tree view, as used by {{{QFileSystemModel}}}
***[[QTreeWidget|http://srinikom.github.io/pyside-docs/PySide/QtGui/QTreeWidget.html]] : provides a tree view that uses a predefined tree model.
** [[QListView|http://srinikom.github.io/pyside-docs/PySide/QtGui/QListView.html]] : provides a list or icon view onto a model, as used by {{{QStringListModel}}}.
*** [[QListWidget|http://srinikom.github.io/pyside-docs/PySide/QtGui/QListWidget.html]] : provides an item-based list widget
** [[QHeaderView|http://srinikom.github.io/pyside-docs/PySide/QtGui/QHeaderView.html]] : provides a header row or header column for item views
** [[QColumnView|http://srinikom.github.io/pyside-docs/PySide/QtGui/QColumnView.html]] : provides a model/view implementation of a column view.
** [[QTableView|http://srinikom.github.io/pyside-docs/PySide/QtGui/QTableView.html]] : provides a default model/view implementation of a table view.
*** [[QTableWidget|http://srinikom.github.io/pyside-docs/PySide/QtGui/QTableWidget.html]] : provides an item-based table view with a default model
** [[QUndoView|http://srinikom.github.io/pyside-docs/PySide/QtGui/QUndoView.html]] : displays the contents of a {{{PySide.QtGui.QUndoStack}}}.
!Selection Models
Deals with user selection in the item view
* [[QItemSelectionModel|http://srinikom.github.io/pyside-docs/PySide/QtGui/QItemSelectionModel.html]] : Keeps track of a view’s selected items, used by {{{QFileSystemModel}}}.
! Examples
This is all pseudo-code: Most of these would be attributes of some class, or methods. I've left off the {{{self.}}} on everything.
{{{
# For the below examples
from PySide import QtCore
from PySide import QtGui
from PySide.QtCore import Qt
}}}
Simple example showing how to make a treeview of a filesystem:
{{{
# Initialization:
# Create a model for a filesystem
fileSystemModel = QtGui.QFileSystemModel()
# Create a view for that model, and assign it:
treeView = QtGui.QTreeView()
treeView.setModel(fileSystemModel)
# Get the treeView's QItemSelectionModel for later usage
itemSelectionModel = treeView.selectionModel()
# Setup a callback for when something is clicked in the view:
treeView.clicked[QtCore.QModelIndex].connect(somethingClicked)
# Setup the default paths to display:
modelIndex = fileSystemModel.setRootPath(startDirString)
treeView.setRootIndex(modelIndex)
#----
# Example 'somethingClicked' callback method:
# Get the QModelIndex for what we picked in our treeView:
dir_modelIndex = itemSelectionModel.currentIndex()
# Get the string version of the directory:
dir_path = fileSystemModel.filePath(dir_modelIndex)
# Now go do something with that data...
}}}
This example shows how to make a view of an arbitrary list of strings:
{{{
# Create a model for the list of strings:
stringModel = QtGui.QStringListModel()
# Set the list of strings to view:
stringModel.setStringList(["stuff", "to","store","in","model"])
# Create a view for that model, and assign it:
listView = QtGui.QListView()
listView.setModel(stringModel )
# Get the ItemSelectionModel for this QListView:
itemSelectionModel = listView.selectionModel()
# Setup a callback for when something is clicked in the view:
listView.clicked[QtCore.QModelIndex].connect(somethingClicked)
#------
# Example 'somethingClicked' callback method:
# The modelIndex is atomically passed to this method:
stringData = index.data()
# Now do something with that string data
# Another method to query what is picked:
itemSelection = itemSelectionModel.selection() # QItemSelection
selIndex = itemSelection.indexes()[0] # QModelIndex
stringData = selIndex.data()
}}}
I read a good descriptions in Maya's ~PySide docs:
<<<
In Qt a layout (i.e. a {{{QLayout}}} or something derived from it) is not a widget. It is attached to a widget to control the positioning of that widget's children but is not itself a child of the widget and does not appear in the widget hierarchy.
<<<
Layouts can:
* Contain multiple child widgets.
* Contain other layouts.
Widgets can:
* Contain multiple child widgets.
* Attach a single layout.
* If both child widgets and a layout are assigned to parental widget, the widgets are always ordered before the layout.
* [[Gallery of Widgets|http://doc.qt.io/qt-5/gallery.html]]
High level overview contrasting widgets and layouts. As I see it, widgets are containers that have events & can draw on-screen. Layouts help organize widgets. For example:
*[[QDialog|http://srinikom.github.io/pyside-docs/PySide/QtGui/QDialog.html]] : Widget : Top level window.
**[[QGridLayout|http://srinikom.github.io/pyside-docs/PySide/QtGui/QGridLayout.html]] : Layout : The top level layout of the window widget: It has two sections, on the left and right side.
***[[QVBoxLayout|http://srinikom.github.io/pyside-docs/PySide/QtGui/QVBoxLayout.html]] : Layout : Child of the main layout, used on the left hand side of the window.
****Bunch of button widgets added here....
***[[QScrollArea|http://srinikom.github.io/pyside-docs/PySide/QtGui/QScrollArea.html]] : Widget : This will be used to scroll its children on the right side of the window. Note the scroller wants to scroll a //widget// (via it's '{{{.addWidget()}}}' method), not a layout. So we need to make a 'container widget' to hold the layout to be scrolled:
****[[QWidget|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html]] : Widget : This is a container widget that is needed hold the layout inside the scroller.
*****[[QVBoxLayout|http://srinikom.github.io/pyside-docs/PySide/QtGui/QVBoxLayout.html]] : Layout : This layout is what is inside the scroller.
******Bunch of child items (sublayouts, widgets) added here for scrolling...
Here are some of the most common methods, and a loose graphical overview of how widgets/layouts relate. Subclassed items can have even more specific methods.
>[[QWidget|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html]]
>Widgets can have a single layout manager, and optionally multiple child widgets that are unmanaged: Their positions would be set absolutely.
>>[[QWidget(parent=None)|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.QWidget]] : The default constructor can accept another widget instance as its parent. It will be added as an unmanaged child (outside the normal layout manager).
>> [[.setLayout|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.setLayout]]( someLayout ) - Can have a single layout manager.
>> [[.setParent|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.setParent]] ( parentWidget) : Add itself to another {{{QWidget}}} as an unmanaged child (outside the normal layout manager)
>> [[.children|http://srinikom.github.io/pyside-docs/PySide/QtCore/QObject.html#PySide.QtCore.PySide.QtCore.QObject.children]]() : Returns a list of child objects which can include both widgets and the layout, if present. Inherited from [[QObject|http://srinikom.github.io/pyside-docs/PySide/QtCore/QObject.html]]
>[[QLayout|http://srinikom.github.io/pyside-docs/PySide/QtGui/QLayout.html]]
>Layouts can have both child widgets and/or other layouts.
>>{{{.addLayout( someLayout )}}} & {{{.insertLayout( index, someLayout )}}} - methods of some layout subclass : Allows a child layout to live in a parental layout. Most layouts allow for multiple child layouts.
>>[[.addWidget|http://srinikom.github.io/pyside-docs/PySide/QtGui/QLayout.html#PySide.QtGui.PySide.QtGui.QLayout.addWidget]] ( someWidget) - Add a widget to this layout. Most layouts support the addition of multiple widgets.
>>[[.count()|http://srinikom.github.io/pyside-docs/PySide/QtGui/QLayout.html#PySide.QtGui.PySide.QtGui.QLayout.count]] - method of some layout subclass : Returns the number of items in the layout.
>>[[.takeAt|http://srinikom.github.io/pyside-docs/PySide/QtGui/QLayout.html#PySide.QtGui.PySide.QtGui.QLayout.takeAt]]( someIndex ) : method of some layout subclass : Remove the item at that index, and return it.
>>[[.itemAt|http://srinikom.github.io/pyside-docs/PySide/QtGui/QLayout.html#PySide.QtGui.PySide.QtGui.QLayout.itemAt]]( someIndex ) : method of some layout subclass : Return the item at that index.
>>[[.indexOf|http://srinikom.github.io/pyside-docs/PySide/QtGui/QLayout.html#PySide.QtGui.PySide.QtGui.QLayout.indexOf]] ( someWidget ) : method of some layout subclass : Returns the index of the given widget.
----
Also see:
*[[PySide : Layout Managers]]
! Views and Models
There are three main components
* The 'view' like ~QTreeView: This is the piece of UI that displays the 'data model'.
* The 'item model', like ~QStandardItemModel : This is the construct that represents your data (items) inside the 'view'.
* The 'selection model', like ~QItemSelectionModel : This interfaces with the 'view' and 'item model' to tell you what the user has selected.
!! Initial setup
Pretty generic:
{{{
self.treeView = QtWidgets.QTreeView() # The 'view'
self.treeView.columnHeaders = ["Col1", "Col2", "Etc..."]
self.itemModel = QtGui.QStandardItemModel(0, len(self.treeView.columnHeaders)) # The 'item model'
for col,colName in enumerate(self.treeView.columnHeaders):
self.itemModel.setHeaderData(col, Qt.Horizontal, colName)
parentItem = self.itemModel.invisibleRootItem()
# Some method that populates the QStandardItemModel with myData
self.populate(parentItem, myData)
self.treeView.setModel(self.itemModel)
self.selectionModel = self.treeView.selectionModel() # The 'selection model' QItemSelectionModel for later use below.
}}}
!! Query what is selected
{{{
modelIndex = self.selectionModel.currentIndex() # QModelIndex
standardItem = self.itemModel.itemFromIndex(selModelIndex) # QStandardItem
print standardItem.text() # string
}}}
!! Register a callback when something is clicked:
{{{
self.treeView.clicked[QtCore.QModelIndex].connect(self.modelClicked)
}}}
!! Register a callback when something is double-clicked:
This doesn't trigger on double-click, but triggers after the user changes the text and presses enter:
{{{
self.itemModel.dataChanged.connect(self.renameItem)
}}}
Which passes a {{{QModelIndex}}} to the (made up name) {{{renameItem}}} method.
!! Select something programatically & scroll to it:
{{{
text = "my search text"
found = []
for standardItem in self.itemModel.findItems(text, flags=Qt.MatchContains): # QStandardItem
found.append(standardItem.index()) # QModelIndx
if found:
self.treeView.scrollTo(found[0]) # QTreeView
self.selectionModel.clear() # If you don't want multiple selection
self.selectionModel.select(found[0], QtCore.QItemSelectionModel.Select)
self.selectionModel.setCurrentIndex(found[0], QtCore.QItemSelectionModel.Select)
}}}
!! Recursively Search
This seems like it would totally work, but it does not if any recursion is required: It only searches the 'root' level of the tree and nothing lower:
{{{
for standardItem in self.itemModel.findItems(text, flags=Qt.MatchContains):
findList.append(standardItem.index())
}}}
So, you need to manually get all the {{{QStandardItem}}}s in the model, then search them for what you're after:
{{{
# First, get all the QStandardItems
findList = []
itemModels = [self.itemModel.invisibleRootItem()]
for itemModel in itemModels:
for i in range(itemModel.rowCount()):
for j in range(itemModel.columnCount()):
item = itemModel.child(i, j)
if item:
itemModels.append(item)
# Then search them for what you're after:
for itemModel in itemModels:
if text.lower().strip() in itemModel.text().lower().strip():
findList.append(itemModel.index()) # QModelIndex
}}}
This post here probably has the best description of it I've ever seen:
https://stackoverflow.com/questions/4553304/understanding-form-layout-mechanisms-in-qt
In case that post ever goes away, recording some of the important stuff here:
What you should be aware of regarding layouts and their size policies:
* Most Qt widgets have a size policy. This size policy tells the system how the widget should stretch or shrink. It's got from the class {{{QSizePolicy}}}. A size policy has both vertical and horizontal components.
* Most widgets also have a size Hint. This size hint tells the system a widgets preferred size.
* {{{QSizePolicy}}} has a stretch factor to allow widgets to grow at different rates.
I am only familiar with 4 size policies:
* fixed size policy - The size of the widget is fixed and it can't be stretched. It remains at its size hint.
* minimum size policy - The size hint is the smallest possible size of the widget, but it _can still_ grow bigger if necessary.
* Preferred size policy - the widget can shrink or grow bigger than its size hint.
* expanding size policy - the widget can shrink or grow bigger than its size hint :)
You may want to ask, What is the difference between preferred and expanding?
Answer: Imagine a form with 2 widgets, one with preferred and another with expanding. Then any extra space will be given to the widget with the expanding policy. The widget with the preferred policy will remain at its size hint.
Why you should care about {{{sizeHint}}}:
* You can see that every widget has a {{{sizeHint}}} which is vital because QT's layout system always respects the {{{sizeHint}}}.
* This is only a problem if the default size of the widget is not exactly what you want.
* The only way around this problem is to extend (subclass) the widget and reimplement its sizeHint() member function.
* And {{{sizeHint()}}} is the recommended size of a QWidget, and the Layout of the widget parent will take sizeHint() and sizePolicy() into consideration to determine the space of the child widget can hold.
----
[[QWidget|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html]] sizing methods:
*[[sizeHint|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.sizeHint]] : Returns a [[QSize|http://srinikom.github.io/pyside-docs/PySide/QtCore/QSize.html]]
*[[sizePolicy|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.sizePolicy]] : Returns [[QSizePolicy|http://srinikom.github.io/pyside-docs/PySide/QtGui/QSizePolicy.html]]
*[[setSizePolicy|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.setSizePolicy]] : Accepts [[QSizePolicy|http://srinikom.github.io/pyside-docs/PySide/QtGui/QSizePolicy.html]]
*[[setMinimumHeight|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.setMinimumHeight]] : Accepts int
*[[setMinimumSize|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.setMinimumSize]] : Accepts either (x,y) or [[QSize|http://srinikom.github.io/pyside-docs/PySide/QtCore/QSize.html#PySide.QtCore.QSize]]
*[[setMinimumWidth|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.setMinimumWidth]] : Accepts int
*[[setMaximumHeight|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.setMaximumHeight]] : Accepts int
*[[setMaximumSize|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.setMaximumSize]] : Accepts either (x,y) or [[QSize|http://srinikom.github.io/pyside-docs/PySide/QtCore/QSize.html#PySide.QtCore.QSize]]
*[[setMaximumWidth|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.setMaximumWidth]] : Accepts int
*[[adjustSize|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.adjustSize]] : Adjusts the size of the widget to fit its contents.
*[[baseSize|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.baseSize]] : This property holds the base size of the widget.
*[[frameSize|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.frameSize]] : This property holds the size of the widget including any window frame.
*[[resize|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.resize]] : Accepts (x,y) or [[QSize|http://srinikom.github.io/pyside-docs/PySide/QtCore/QSize.html#PySide.QtCore.QSize]] : This property holds the size of the widget excluding any window frame.
*[[setBaseSize|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.setBaseSize]] : Accepts (x,y) or [[QSize|http://srinikom.github.io/pyside-docs/PySide/QtCore/QSize.html#PySide.QtCore.QSize]] : This property holds the base size of the widget.
*[[setFixedSize|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.setFixedSize]] : Accepts (x,y) or [[QSize|http://srinikom.github.io/pyside-docs/PySide/QtCore/QSize.html#PySide.QtCore.QSize]] : Sets both the minimum and maximum sizes of the widget to s , thereby preventing it from ever growing or shrinking.
*[[size|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.size]] : Returns [[QSize|http://srinikom.github.io/pyside-docs/PySide/QtCore/QSize.html]]
*[[geometry|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.geometry]] : Returns [[QRect|http://srinikom.github.io/pyside-docs/PySide/QtCore/QRect.html#PySide.QtCore.QRect]] :This property holds the geometry of the widget relative to its parent and excluding the window frame.
*[[frameGeometry|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.frameGeometry]] : Returns [[QRect|http://srinikom.github.io/pyside-docs/PySide/QtCore/QRect.html#PySide.QtCore.QRect]] : This property holds geometry of the widget relative to its parent including any window frame.
*[[setGeometry|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#PySide.QtGui.PySide.QtGui.QWidget.setGeometry]] : Accepts (x, y, w, y) or [[QRect|http://srinikom.github.io/pyside-docs/PySide/QtCore/QRect.html#PySide.QtCore.QRect]] : This property holds the geometry of the widget relative to its parent and excluding the window frame.
~QWidget docs for [[Size Hints and Size Policies|http://srinikom.github.io/pyside-docs/PySide/QtGui/QWidget.html#size-hints-and-size-policies]]
----
I read a good descriptions in Maya's ~PySide docs:
<<<
In Qt a layout (i.e. a {{{QLayout}}} or something derived from it) is not a widget. It is attached to a widget to control the positioning of that widget's children but is not itself a child of the widget and does not appear in the widget hierarchy.
<<<
[[QLayoutItem|http://srinikom.github.io/pyside-docs/PySide/QtGui/QLayoutItem.html#PySide.QtGui.QLayoutItem]] sizing methods:
*[[maximumSize|http://srinikom.github.io/pyside-docs/PySide/QtGui/QLayoutItem.html#PySide.QtGui.PySide.QtGui.QLayoutItem.maximumSize]] : Returns [[QSize|http://srinikom.github.io/pyside-docs/PySide/QtCore/QSize.html#PySide.QtCore.QSize]]
*[[minimumSize|http://srinikom.github.io/pyside-docs/PySide/QtGui/QLayoutItem.html#PySide.QtGui.PySide.QtGui.QLayoutItem.minimumSize]] : Returns [[QSize|http://srinikom.github.io/pyside-docs/PySide/QtCore/QSize.html#PySide.QtCore.QSize]]
*[[sizeHint|http://srinikom.github.io/pyside-docs/PySide/QtGui/QLayoutItem.html#PySide.QtGui.PySide.QtGui.QLayoutItem.sizeHint]] : Returns [[QSize|http://srinikom.github.io/pyside-docs/PySide/QtCore/QSize.html#PySide.QtCore.QSize]]
*[[geometry|http://srinikom.github.io/pyside-docs/PySide/QtGui/QLayoutItem.html#PySide.QtGui.PySide.QtGui.QLayoutItem.geometry]] : Returns [[QRect|http://srinikom.github.io/pyside-docs/PySide/QtCore/QRect.html#PySide.QtCore.QRect]]
[[QLayout|http://srinikom.github.io/pyside-docs/PySide/QtGui/QLayout.html]] sizing methods:
*[[setContentsMargins|https://srinikom.github.io/pyside-docs/PySide/QtGui/QLayout.html#PySide.QtGui.PySide.QtGui.QLayout.setContentsMargins]] : Set the margins around the children of this layout. : {{{setContentsMargins(2,2,2,2)}}}
* [[setSpacing|https://srinikom.github.io/pyside-docs/PySide/QtGui/QLayout.html#PySide.QtGui.PySide.QtGui.QLayout.setSpacing]] : Set the spacing between the child widgets of this layout: {{{setSpacing(2)}}}.
*[[sizeConstraint|http://srinikom.github.io/pyside-docs/PySide/QtGui/QLayout.html#PySide.QtGui.PySide.QtGui.QLayout.sizeConstraint]] : Returns [[QLayout.SizeConstraint|http://srinikom.github.io/pyside-docs/PySide/QtGui/QLayout.html#PySide.QtGui.PySide.QtGui.QLayout.SizeConstraint]]
*[[setSizeConstraint|http://srinikom.github.io/pyside-docs/PySide/QtGui/QLayout.html#PySide.QtGui.PySide.QtGui.QLayout.setSizeConstraint]] : Accepts [[QLayout.SizeConstraint|http://srinikom.github.io/pyside-docs/PySide/QtGui/QLayout.html#PySide.QtGui.PySide.QtGui.QLayout.SizeConstraint]] :
**{{{QLayout.SetDefaultConstraint}}} The main widget’s minimum size is set to {{{QLayout.minimumSize()}}}, unless the widget already has a minimum size.
**{{{QLayout.SetFixedSize}}} The main widget’s size is set to {{{QLayoutItem.sizeHint()}}} ; it cannot be resized at all.
**{{{QLayout.SetMinimumSize}}} The main widget’s minimum size is set to {{{QLayout.minimumSize()}}} ; it cannot be smaller.
**{{{QLayout.SetMaximumSize}}} The main widget’s maximum size is set to {{{QLayout.maximumSize()}}} ; it cannot be larger.
**{{{QLayout.SetMinAndMaxSize}}} The main widget’s minimum size is set to {{{QLayout.minimumSize()}}} and its maximum size is set to {{{QtGui.QLayout.maximumSize()}}} .
**{{{QLayout.SetNoConstraint}}}The widget is not constrained.
If a [[QLayout|http://srinikom.github.io/pyside-docs/PySide/QtGui/QLayout.html]] manages the widgets children, and the widgets haven't had their values overridden, then the layouts police is used instead.
!!!Examples:
Make a button that completely fills its parent layout. When you make a new {{{QSizePolicy}}} you specify the horizontal and vertical policies. In this case, we just say to 'ignore' them all, so it takes up the maximum space:
{{{
from PySide import QtGui
myBigBut = QtWidgets.QPushButton("boom")
sp = QtGui.QSizePolicy(QtWidgets.QSizePolicy.Ignored, QtWidgets.QSizePolicy.Ignored)
myBigBut.setSizePolicy(sp)
}}}
Make a button that has a fixed size, that won't change:
{{{
myBigBut = QtWidgets.QPushButton("boom")
myBigBut.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
}}}
Make a button that has the smallest size possible. Yes, this looks backwards because {{{Maximum}}} is used, but that's how it seems to work.
{{{
myBigBut = QtWidgets.QPushButton("boom")
myBigBut.setSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
}}}
Make a widget as big as possible:
{{{
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
# This can be really important to give this widget priority over others:
sizePolicy.setVerticalStretch(2)
myWidget.setSizePolicy(sizePolicy)
}}}
Say you make some spinbox, that connects its signal to some other method:
{{{
self.mySpinBox = SpinBox()
self.mySpinBox.valueChanged.connect(self.updateSomeValue)
}}}
Whenever you change the value via the UI, the signal triggers the other {{{updateSomeValue}}} method.
Then in some other method, you update your ui values with presets/defaults, after they're created:
{{{
self.mySpinBox.setValue(presetVal)
}}}
Which //also// triggers the {{{updateSomeValue}}} method. And you may not want that trigger to happen when the presets are loaded.
To get around that you need to first disable the signals on your widget, set the value, then re-enable the signals:
{{{
self.mySpinBox.blockSignals(True)
self.mySpinBox.setValue(val)
self.mySpinBox.blockSignals(False)
}}}
Docs: [[QObject.blockSignals()|http://srinikom.github.io/pyside-docs/PySide/QtCore/QObject.html#PySide.QtCore.PySide.QtCore.QObject.blockSignals]]
Per: https://tech-artists.org/t/pyside2-looking-for-a-specific-class/13719/5
https://doc.qt.io/qtforpython-5/PySide2/QtWidgets/QGroupBox.html
Example code, showing how to make it collapse and expand, with custom arrow icons:
{{{
def populate(self):
"""
Create the primary contents of our widget.
"""
self.layout_main = QtWidgets.QVBoxLayout(self)
if self.layout_main:
self.widget_groupBox = QtWidgets.QGroupBox("A Groupbox!")
self.widget_groupBox.setCheckable(True)
self.layout_main.addWidget(self.widget_groupBox)
self.widget_groupBox.setStyleSheet(
"QGroupBox::indicator:checked {"
"image: url(:/arrowDown.png);"
"}"
"QGroupBox::indicator:unchecked {"
"image: url(:/arrowRight.png);"
"}"
)
self.widget_groupBox.clicked.connect(self.expandCollapse)
# Add some contents to our QGroupBox
self.layout_groupbox = QtWidgets.QVBoxLayout()
self.widget_groupBox.setLayout(self.layout_groupbox)
if self.layout_groupbox:
widget_but = QtWidgets.QPushButton("a button")
self.layout_groupbox.addWidget(widget_but)
self.layout_groupbox.addWidget(QtWidgets.QLabel("Inside the Groupbox"))
# Need this for the 'collapse' effect to have the look we want.
self.layout_main.addStretch()
def expandCollapse(self):
"""
Show/hide the contents of our QGroupBox, to make it look like it's collapsing
and expanding.
"""
widgets = [item for item in self.widget_groupBox.children() if isinstance(item, QtWidgets.QWidget)]
if self.widget_groupBox.isChecked():
for wid in widgets:
wid.show()
else:
for wid in widgets:
wid.hide()
}}}
----
Also, this, is more complicated, but also works:
https://stackoverflow.com/questions/52615115/how-to-create-collapsible-box-in-pyqt
This will open a web page in your default browser:
{{{
from PySide.QtGui import QDesktopServices
QDesktopServices.openUrl("http://www.google.com")
}}}
http://srinikom.github.io/pyside-docs/PySide/QtGui/QDesktopServices.html
----
This will open a web page in a new ~PySide window:
{{{
from PySide.QtCore import QUrl
from PySide.QtWebKit import QWebView, QWebSettings
url = QUrl( 'http://www.google.com' )
wv = QWebView()
wv.settings().setAttribute( QWebSettings.PluginsEnabled, True ) # Needed?
wv.load(url)
wv.show()
}}}
http://srinikom.github.io/pyside-docs/PySide/QtWebKit/index.html
http://srinikom.github.io/pyside-docs/PySide/QtWebKit/QWebView.html
http://srinikom.github.io/pyside-docs/PySide/QtWebKit/QWebSettings.html
http://srinikom.github.io/pyside-docs/PySide/QtCore/QUrl.html
* Make the [[QTabWidget|https://doc.qt.io/qtforpython-5/PySide2/QtWidgets/QTabWidget.html]]
* Add it to the parent layout.
* For each thing you want to be a tab:
** Make an empty widget
** Add a layout to the empty widget.
** Add to ~QTabWidget : {{{widget_tabs.addTab(widget_thisTab, "some tab name")}}}
To detect when a user changes a tab:
* {{{widget_tabs.currentChanged.connect(self.cb_tabChanged)}}}
Then in the callback:
{{{
def cb_tabChanged(self, *args):
print(args)
}}}
where args is a tuple: {{{(intTabIndex, )}}}
Telling you which tab was clicked on.
You can set the tab index via:
{{{
widget_tabs.setCurrentIndex(index)
}}}
A full list can be found here: https://docs.python.org/3/library/2to3.html
Under this section: https://docs.python.org/3/library/2to3.html#fixers
{{{2to3}}} is an exe that lives in the {{{\Scripts}}} dir of your Python install, that can be ran from a shell, to process a whole directory. It's easy to check that whole dir out in your version control softare, and run something like this:
{{{
> C:\path\to\python\Scripts> 2to3 -w -n C:\path\to\my\old\python27\modules
}}}
* {{{-w}}} : Write the changes to the files: If you leave this out, it will just print a preview of what its going to do.
* {{{-n}}} : Don't store a backup of the old file.
@@Important@@ : {{{2to3}}} appears to operate on {{{.py}}} files by default only: It ill skip over {{{.pyw}}} files: You'll have to run it on them specifically.
Then you can 'revert unchanged' in your VC software, and diff the files to see the changes made, test & submit.
----
! Things {{{2to3}}} misses
You'll need to manually fixup this stuff:
{{{logging}}}
* Python 2 :{{{logging._levelNames}}}
* Python 3: {{{logging._levelToName}}}
----
What are the differences I have encountered:
!print
{{{print}}} was a statement in 2, but a function in 3:
{{{
#Py2
print "spam"
#Py3
print("spam")
# Has the new 'sep(arator)' arg, which is handy for
# printing lists without a loop by unpacking them via '*':
myList = [1,2,3]
print(*myList, sep="\n")
1
2
3
}}}
!Exceptions
In exception handling, Py2, uses a comma '{{{,}}}' to pass the exception to a variable, in Py3, they use {{{as}}}:
{{{
#Py2
try:
pass
except Exception, e:
print e
#Py3:
try:
pass
except Exception as e:
print(e)
}}}
!Input
{{{
#Py2:
raw_input("Enter stuff here:")}
#Py3
input("Enter stuff here:")}
}}}
!cPickle
Not a thing in Python3 : Just use regular ol' pickle. See [[here|https://askubuntu.com/questions/742782/how-to-install-cpickle-on-python-3-4]].
{{{
import pickle
}}}
!reload
{{{
try:
reload # Py2
except NameError:
from importlib import reload # Py3
}}}
!xrange
Not a thing in Python 3, just use {{{range}}} : In fact, {{{xrange}}} from Python 2 was renamed to {{{xrange}}} in Python 3, and the Python 2 {{{range}}} was removed. See [[here|https://stackoverflow.com/questions/15014310/why-is-there-no-xrange-function-in-python3]].
!basestring
Gone, see [[here|https://portingguide.readthedocs.io/en/latest/strings.html#type-checking]]. Now gotta use something like either:
{{{
if isinstance(someThing, (str, bytes)):
pass
}}}
Or
{{{
# Requires external package install
import six
if isinstance(someThing, six.string_types):
pass
}}}
! generators missing their next() method
{{{2to3}}} appears to miss this one... :(
{{{
dirWalker = os.walk(someDirPath)
# Python 2
assets = dirWalker.next()[1]
# Python 3
assets = next(dirWalker)[1]
}}}
Just some references I've found:
*[[Thinking In Python|http://mindview.net/Books/TIPython]] - Bruce Eckle - Free book download
*https://sourcemaking.com/design_patterns : Great list of examples
*{{{.py}}} -- Standard text-based Python file ([[module]]), authored //in Python//. To be considered Python 'source code'.
*{{{.pyc}}} -- 'Python Compiler Script'. A 'bytecode compiled' version of a .py file. Generated automatically when a .py module is //[[import]]ed//. It sits 'in-between' the 'source' .py file, and the runtime (Python Virtual Machine).
*{{{.pyd}}} & {{{.dll}}} (Win) -- {{{.so}}} (Linux) -- 'Python Dynamic Module'. They are in the format of a .DLL file; intended specifically as a Python extension. Written in C\C++ (thus not authored //in// Python). They can be imported and executed like {{{.py}}} files.
*{{{.pyo}}} -- 'Python Optimized Byte Code'. Also contains bytecode. Can be executed with the {{{-O}}} command line flag. They can run slightly faster than {{{.pyc}}} files.
*{{{.zip}}} -- Haven't tested this, but apparently it works too, by extracting the {{{.zip}}} automatically when imported.
!Wing:
Personal favorite, see my subject [[Wing IDE]]
!Eclipse:
Very popular in the Java world, but does Python too.
*Main page: http://eclipse.org/
*And for Python support, requires Pydev plugin: http://pydev.org/
**Pydev blog: http://pydev.blogspot.com/
**Pydev supports development for Python, [[Jython|http://www.jython.org/]], and [[IronPython|http://ironpython.net/]] (.NET)
!~PyScripter
http://code.google.com/p/pyscripter/
*"~PyScripter is a free and open-source Python Integrated Development Environment (IDE) created with the ambition to become competitive in functionality with commercial Windows-based ~IDEs available for other languages. Being built in a compiled language is rather snappier than some of the other Python ~IDEs and provides an extensive blend of features that make it a productive Python development environment."
http://www.python.org/dev/implementations/
*[[CPython|http://python.org/]] : The standard distribution of Python, the one you get off of python.org. It //is Python// implemented via the ''C'' programming language.
*[[Jython|http://www.jython.org/]] : (originally called ~JPython) Targeted for interaction with the Java programming language. Consists of Java classes that compile Python source code into Java byte code and route that to the Java Virtual Machine (JVM). It //is Python//, but implemented via ''Java'' (rather than C).
*[[IronPython|http://www.codeplex.com/IronPython]] : Designed to allow Python to integrate with apps coded to work with Microsoft's {{{.NET}}} Framework for Windows (authored in {{{C#}}}), as well as the {{{Mono}}} open source equivalent for Linux. It //is Python//, implemented via ''.NET'' and ''Silverlight'' (rather than C).
*[[Stackless Python|http://www.stackless.com/]] : "Stackless Python is an enhanced version of the Python programming language. It allows programmers to reap the benefits of thread-based programming without the performance and complexity problems associated with conventional threads."
*[[Cython|http://cython.org/]] : "Cython is a language that makes writing C extensions for the Python language as easy as Python itself. Cython is based on the well-known Pyrex, but supports more cutting edge functionality and optimizations. The Cython language is very close to the Python language, but Cython additionally supports calling C functions and declaring C types on variables and class attributes. This allows the compiler to generate very efficient C code from Cython code. This makes Cython the ideal language for wrapping external C libraries, and for fast C modules that speed up the execution of Python code. "
!!Official web:
*[[3.x Python Documentation|http://docs.python.org/3.1/]]
**[[What's new|http://docs.python.org/3.1/whatsnew/index.html]]
**Detailed Release Notes:
***[[3.1.1|http://svn.python.org/projects/python/tags/r311/Misc/NEWS]] [[3.1|http://svn.python.org/projects/python/tags/r31/Misc/NEWS]] [[3.0.1|http://svn.python.org/projects/python/tags/r301/Misc/NEWS]] [[3.0|http://svn.python.org/projects/python/tags/r30/Misc/NEWS]]
----
*[[2.x Python Documentation|http://docs.python.org/index.html]] (main)
**[[What's new|http://docs.python.org/whatsnew/index.html]]
**Detailed Release Notes:
***[[2.6.2|http://www.python.org/download/releases/2.6.2/NEWS.txt]] [[2.6.1|http://www.python.org/download/releases/2.6.1/NEWS.txt]] [[2.6|http://www.python.org/download/releases/2.6/NEWS.txt]] [[2.5.4|http://www.python.org/download/releases/2.5.4/NEWS.txt]] [[2.5.3|http://www.python.org/download/releases/2.5.3/NEWS.txt]] [[2.5.2|http://www.python.org/download/releases/2.5.2/NEWS.txt]] [[2.5.1|http://www.python.org/download/releases/2.5.1/NEWS.txt]] [[2.5|http://www.python.org/download/releases/2.5/NEWS.txt]]
**[[Download the documentation|http://docs.python.org/download.html]]
**[[Global Module Index|http://docs.python.org/modindex.html]]
**[[Python Reference Manual|http://docs.python.org/ref/ref.html]]
**[[Python Library Reference|http://docs.python.org/lib/lib.html]] (below listed things I access on a more regular basis)
***[[Built-in Functions|http://docs.python.org/lib/built-in-funcs.html]] (always available via the Python interpreter)
***[[Built-in Types|http://docs.python.org/lib/types.html]] (The principal built-in types are numerics, sequences, mappings, files classes, instances and exceptions)
***[[Built-in Exceptions|http://docs.python.org/lib/module-exceptions.html]]
***[[Built-in Constants|http://docs.python.org/lib/node8.html]]
***[[Python Runtime Services|http://docs.python.org/lib/python.html]] (provide a wide range of services related to the Python interpreter and its interaction with its environment)
***[[Generic Operating System Services|http://docs.python.org/lib/allos.html]]
***[[Multimedia Services|http://docs.python.org/lib/mmedia.html]]
***[[String Services|http://docs.python.org/lib/strings.html]] (provide a wide range of string manipulation operations)
***[[Structured Markup Processing Tools|http://docs.python.org/lib/markup.html]] (Have Python play with HTML, SGML, & XML)
***[[Graphical User Interfaces with Tk|http://docs.python.org/lib/tkinter.html]]
**[[Python 'How-to's'|http://docs.python.org/dev/howto/index.html]]
----
*[[Search Python Resources|http://www.python.org/search/]]
*[[Python Package Index|http://pypi.python.org/pypi/]] (see [[Packages]])
*[[Python FAQ|http://www.python.org/doc/faq/]]
*[[PEP 8 -- Style Guide for Python Code|http://www.python.org/dev/peps/pep-0008/]]
*[[mail.python.org|http://mail.python.org/mailman/listinfo]] - A listing of all the public mailing lists on mail.python.org
!!Unofficial web:
*[[pyschools|http://www.pyschools.com/]]
*[[Hidden features of Python|http://stackoverflow.com/questions/101268/hidden-features-of-python]] : From Stack Overflow.
*Python [[Quick Reference Cards|http://www.limsi.fr/Individu/pointal/python/pqrc/]] (for Python 2.4)
*[[Python Module of the Week|http://www.doughellmann.com/PyMOTW/contents.html]] Great notes on a big chunk of the Python standard library.
*[[Python Package Index|http://pypi.python.org/pypi]] (a repository of software for the Python programming language)
*[[Python Tips, Tricks, and Hacks|http://www.siafoo.net/article/52]]
*[[ShowMeDo|http://showmedo.com/videos/python]] - Videos showing you how to use Python, nice! I've seen recommendations to [[this|http://showmedo.com/videos/?author=709]] author.
*[[Python 2.0 Quick Reference|http://www.brunningonline.net/simon/python/quick-ref2_0.html]] - nice overview.
*[[Python Tutorials for kids 8+|http://python4kids.wordpress.com/]]
*[[Google's Python Class|http://code.google.com/edu/languages/google-python-class/index.html]]
*[[Introduction to Python|http://lionel.chimou.com/python_for_beginners/]] : Lots of good small examples
----
''On your local disk'' (based on Python install location):
*[[Interactive Python Help]]
!!Books:
*[[Python Programming for the Absolute Beginner - Michael Dawson|http://www.courseptr.com/ptr_detail.cfm?group=Programming&subcat=Other&isbn=978-1-59863-112-8]] - I started learning Python with this book (first edition), @@recommended if you start out a noob like me@@.
*[[Python Pocket Reference - Mark Lutz|http://oreilly.com/catalog/9780596009403/index.html]] - Feels nice in the palm of your hand.
*[[Python Phrasebook - Brad Dayley|http://www.informit.com/store/product.aspx?isbn=0672329107]] - Same size as pocket reference, but more actual code examples given for tasks. Good stuff.
*[[Learning Python - Mark Lutz|http://oreilly.com/catalog/9780596513986/index.html]] - @@I've pulled a //lot// from this one@@, after graduating from 'Python Programming for the Absolute Beginner'
*[[Python Cookbook - various|http://oreilly.com/catalog/9780596007973/index.html]] - If you're tired of looking to the web for examples, this is a good one to read by the fire, with a glass of wine.
*[[Python Programming - Mark Lutz|http://oreilly.com/catalog/9780596009250/index.html]] - This appears to be the mothership. I have yet to get it, but some day, I will.
*http://www.packtpub.com/ : Seems to have a good selection of Python material covering many subjects.
!!Online Books (free):
*A list of free online Python books can be found [[here|http://www.e-booksdirectory.com/programming.php#python]].
*[[Dive Into Python - Mark Pilgrim|http://diveintopython.org/]] - I have yet to spend much time with this, but the whole book is available to download for free, nice!
*[[Invent Your Own Computer Games With Python|http://inventwithpython.com/]] : "...is a free e-Book that teaches you how to program in the Python programming language. Each chapter gives you the complete source code for a new game, and then teaches the programming concepts from the example."
*[[Learn Python The Hard Way|http://learnpythonthehardway.org]] "The book is a very beginner book for people who want to learn to code. If you can already code then the book will probably drive you insane. It's intended for people who have no coding chops to build up their skills before starting a more detailed book. "
*[[Building Skills In Programming|http://homepage.mac.com/s_lott/books/nonprogrammer.html]]
*[[Building Skills In Python|http://homepage.mac.com/s_lott/books/python.html]]
*[[Building Skills in Object-Oriented Design|http://homepage.mac.com/s_lott/books/oodesign.html]]
!!Magazines:
*[[PyMag|http://pymag.phparch.com/]] - Do you want Python delivered to your doorstep once a month?
**I've been subscribing to this since Dec 2008. While (as of this authoring, March 2009) much of it is over my head, it does provide a lot of inspiration, and a good source of Python applications in the real wor.d
*[[The Python: Rag|http://www.pythonrag.org/]] : A monthly .pdf magazine.
*[[Py|http://www.pyzine.com]] - Online zine, but hasn't been updated in years.
This is my overview of Python. Probably going to be different from other people's overviews since it's heavily skewed based around what I use Python for: Authoring tools and pipelines on the technical art (characters specifically) side of video game development. But I thought it would be good, for my own brain, to write down high-level features of the language to get a better understanding of it myself. And based on the time of this authoring, it's all still based on Python 2.6, since that's what I use.
@@Very, very very (very) work in progress.@@ Will update it from time to time...
!Things Python Comes With:
*[[Great Documentation|http://www.python.org/doc/]] (some callouts below):
**[[Glossary|http://docs.python.org/glossary.html#glossary]]
**[[Language Reference|http://docs.python.org/reference/]]
*[[The Standard Library|http://docs.python.org/library/index.html]] : This encompass everything that ships with the standard install of Python. I break it down into three main areas: Built-in //functions//, built-in //types//, built-in (global) //modules//:
**[[Built-in functions|http://docs.python.org/library/functions.html]]. These functions come with the standard install. You always have them at your fingertips.
**[[Built-in types|http://docs.python.org/library/stdtypes.html]] : Sequences, numeric, comparison, Boolean, iterator, generator, string, etc. If a piece of built-in data has a 'type', this is where you find it. When you assign a value to a variable, the value will assume a given 'type'.
**[[Global Modules|http://docs.python.org/modindex.html]] : These modules, like built-in functions, area always available, but must be imported before usage.
**There are more than this though: The Standard Library link lists the rest: Built-in Constants, Built-in Exceptions, etc. Everything after that is a more organized list of the Global Modules.
!Implementations of Python:
I think of Python as a concept, or a syntax, or a way of doing things. The way that concept\syntax is implemented can vary. The default implementation of Python is via the C programming language, and is known as '~CPython'. But there are others. For example, Jython is the same python syntax as ~CPython, but implemented in Java. This lets you create Java code, but author it via the Python syntax, which is pretty slick. Find a more robust list under my subject: [[Python Implementations]].
!General Concepts:
!!! Statements and Expressions
Statements are one or more lines of Python code that give Python orders. Expressions do the work that return values. See my notes on [[Statement]]. For example
{{{
stuff = 2 + 3
}}}
That is an 'assignment statement'. {{{2 + 3}}} is the expression, which returns a value (which becomes an integer object) which the variable name {{{stuff}}} is assigned to.
!!!Importing, namespaces, and attributes:
!!!What's with all those {{{__}}}underscores{{{__}}}?
Lib notes [[here|http://docs.python.org/reference/lexical_analysis.html#reserved-classes-of-identifiers]]
!Scope
!!!Local
Function Level
!!!Global
Module Level
!!!Universal
Built-in Level
!Packages & Pathing
!Language Features
Functions, modules, and concepts that I find to be darn handy.
!!Functions:
!!!lambda
!!!map
!!!filter
!!!reduce
!!!dir
!!Concepts:
!!!parameters & arguments
!!!unpacking variables
!!!decorators
!!!list comprehentions
!!!Dynamically Typed Language
*Not typed as in 'you typed something', but the 'types of data' are dynamically assigned at time of creation:
<<<
{{{
# Python
spam = 23 # Dynamically typed
# Java
int spam = 23; # Strongly typed
}}}
In the Python example, 23 becomes an integer type, that the variable {{{spam}}} simply points to.
In the Java example, we create a variable named spam that we define as an integer type, and assign it the value of 23.
<<<
!Object Oriented Programming
!!!Properties
!!!Operator Overloading
!!!Polymorphism
[[Blender|www.blender.org]] is free, open-source computer animation software. I've never gotten around to learning it, despite the fact I'd really like to (currently [[Processing|www.processing.org]] takes up most my free dev time...).
Blender is based around Python however, so if you have a hankerin' to do some full-blown 3D with Python...
You can find their "Scripting" documentation page here: http://www.blender.org/development/
And the current link (Blender 2.48) to the Python API is here: http://www.blender.org/documentation/248PythonDoc/
----
Video describing Python integration with Blender 2.5: (major update version for Blender)
http://python.mirocommunity.org/video/1716/using-python-for-blender-anima
* The eBook [[Music For Geeks And Nerds|http://musicforgeeksandnerds.com/]]
Really verbose comparison of PHP, Perl, Python, Ruby:
http://hyperpolyglot.org/scripting
That site actually has comparisons for many other languages as well:
http://hyperpolyglot.org/
I ran across this blog post that compares several with code examples. Nice.
http://stackoverflow.com/questions/326300/python-best-library-for-drawing
*http://networkx.lanl.gov/ - for graphing & plotting
I have a whole other wiki dedicated to Maya, and mel (its scripting language) specifically. For ~Maya-Python related stuff, you can find it there too:
http://mayamel.tiddlyspot.com/
Check out the 'PYTHON' catagory:
http://mayamel.tiddlyspot.com/#PYTHON
*Original blog: http://blog.jimmy.schementi.com/2010/03/pycon-2010-python-in-browser.html
This blog post goes on to explain how to make this happen, via [[IronPython|http://ironpython.net/]] and [[Microsoft Silverlight|http://www.silverlight.net/]]
----
This now has an official home as well, with examples and more instruction:
*http://ironpython.net/browser/
What happens when you get one of these?
{{{
RuntimeError: Bad magic number in .pyc file
}}}
or
{{{
ImportError: bad magic number in 'myModule': b'\x03\xf3\r\n' #
}}}
Just delete the {{{.pyc}}} file, and rerun the module. I'm told it means the {{{.pyc}}} was compiled against a different version of Python, and needs to be recompiled.
*[[Python for Android|https://github.com/kivy/python-for-android]] - Not yet used this.
*[[Scripting Layer For Android|http://code.google.com/p/android-scripting/]] (SL4A).
**I have notes on my blog for setting this up. [[Install SL4A on the Emulator|http://www.akeric.com/blog/?p=879]], [[Install SL4A on an Android phone|http://www.akeric.com/blog/?p=1250]].
Different setup than Python on a PC: Mac comes with Python, PC doesn't. When you install it on the PC, you're usually installing the current version (or any version you choose). But the mac already has it installed in it's Frameworks structure, and it's usually //not// the current version. Here is some documentation on the issue:
*http://www.python.org/download/mac/
*http://wiki.python.org/moin/MacPython
*http://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man1/python.1.html
Places to paste Python code for good quality sharing:
*http://codepad.org/
This blog post talks about it:
http://tech-artists.org/forum/showthread.php?t=1304
And here is some code:
https://bitbucket.org/amorano/pyps
There has been reported success building this in Visual Studio 2008 on Windows, using Photoshop CS 5.1 and Python 2.6.
You'll need the Photoshop SDK:
http://www.adobe.com/devnet/photoshop/sdk.html
This is closely tied to Python [[namespace]]s.
Python has three (well, possibly four, see below) scopes that variables can be found in:
*{{{__main__}}} : The top most scope in Python (where {{{__builtins__}}} live): If you execute a [[Statement]] from the interactive prompt, it is local to this location. It's also the scope of a module when its icon is double-clicked. See Python [[docs|http://docs.python.org/lib/module-main.html]]
**{{{globals()}}} : The scope of the current module (if currently executing in a module). See Python [[docs|http://docs.python.org/ref/exec.html#l2h-587l]]
***{{{locals()}}} : The scope of the current function (if currently executing in a function). This scope can actually be in an 'enclosing local scope', if function definitions are nested (thus adding another scope to search). See Python [[docs|http://docs.python.org/ref/exec.html#l2h-587l]]
If you execute an expression like such:
{{{
print foo
}}}
Python first searches for variable names in {{{locals()}}} scope, then the 'enclosing locals scope' (if present), then {{{globals()}}} scope, and finally {{{__main__}}} scope. If {{{foo}}} was defined in both a parental module, //and// the current function being executed, the definition in the function would be used, since its searched first.
>{{{__main__}}}
>Search here fourth. This is also where {{{__builtins__}}} live. I call this the 'universal' scope. It's also known as the 'builtin' scope. Is {{{foo}}} here? If not, raise an Exception.
>>{{{someModule.py}}} - {{{globals()}}}
>>Global scope. Search here third. Is {{{foo}}} here? If not, look one scope higher.
>>>{{{someEnclosingFunction()}}} - {{{locals()}}}
>>>Enclosing Local scope. Search here second (if present). Functions can be nested in functions.
>>>>{{{someFunction()}}} - {{{locals()}}}
>>>>Local scope. Search here first. Is {{{foo}}} here? If not, look one scope higher.
{{{locals()}}} and {{{globals()}}} are both built-in functions (from the {{{__builtin__}}} module) that return dictionaries of the variables defined at the specified scope.
The {{{global}}} //command// however lets you point to 'global' variables in a 'local' scope:
{{{
# someModule.py - starts global scope
gVar = 23 # define global var gVar
lVar = 100 # define global var lVar
def myDef(): # enter local scope
global gVar # define gVar in this scope to be global
gVar = "foo!" # update global var gVar
lVar = "boo!" # define new *local* var lVar
print gVar, lVar
# 23 100
myDef()
print gVar, lVar
# foo! 100
}}}
----
{{{<<}}}''Tangent''{{{>>}}}
<<<
Everything defined in the {{{__builtin__}}} module is local to the {{{__main__}}} scope. However (and this is my personal assumption), {{{__builtin__}}} is imported into {{{__main__}}} in the [[namespace]] {{{__builtins__}}} (note the 's'). I've heard the location that {{{__builtin__}}} lives in as '//the implied outer built-in scope//'. {{{__builtin__}}} is always present, always there, freely giving you its goodness. This is why you //don't// have to type this to access its functions:
{{{
import __builtin__
__builtin__.globals()
# I mean, you could do this... but why all the extra typing?
}}}
{{{
# Just do:
globals()
# instead, without need of the previous import.
# __builtin__ has already been imported by Python, so you don't need to do it.
}}}
I'm not sure exactly how this works in practice, but one theory I have is that when Python starts, it does something like this:
{{{
# import __builtin__ in the __builtins__ namespace:
import __builtin__ as __builtins__
# give user direct access to all modules in __builtin__
from __builtin__ import *
}}}
But I'm just guessing here...
<<<
{{{<<}}}''End Tangent''{{{>>}}}
----
When you interactively enter [[Statement]]s in Python (say, at the command line, or via IDLE), they are added to {{{__main__}}}'s dictionary {{{__dict__}}} for subsequent retrieval. Since {{{__main__}}} is the 'top level script environment', variables defined there are seen in all other modules. They're not 'global', I call them 'universal' ;)
{{{
# Define a variable, which is assigned to __main__.__dict__:
foo = 23
# Since this was defined in __main__, we can access directly:
print foo
# 23
# To actually see where that data physically lives:
import main
print __main__.__dict__["foo"]
# 23
}}}
However, as shown above, to actually access {{{__main__.__dict__}}}, you first need to import it.
----
''Universal scope''
That's a term I made up just for Python. So: Globals is module level. Locals is function level. What's above globals?
As mentioned above, {{{__main__}}} is the top most module. But if you truly want to store persistent data between modules, you can modify the {{{__builtin__}}} namespace that all modules share, or the module-level specifc import of {{{__builtin__}}}: '{{{___builtins__}}}' (note the 's')
{{{
# moduleA.py
import __builtin__
__builtin__.spam = 42
# __builtins__ already exists in the module as a dictionary, no need to import:
__builtins__["ham"] =24
}}}
{{{
# moduleB.py
# this will fail if moduleA isn't executed first
print spam, ham
}}}
{{{
>>> import moduleA
>>> import moduleB
42 24
}}}
As you can see, in {{{moduleB.py}}}, we don't do any importing, we just {{{print spam, ham}}}. And since {{{moduleA.py}}} had previously updated {{{__builtin__}}} with the 'foo attribute', and the {{{__builtins__}}} dict with the 'ham' key, it was then visible to any other module.
I should say that many would frown on working this way, and I'm not saying you should. But I do think its important to understand how things work.
----
Also see:
*[[Understanding __dict__]]
The only way I can find via the Standard Library is via {{{Tkinter}}}'s {{{PhotoImage}}} class:
{{{
import Tkinter
# Need to call to Tk, I guess to initialize things?
root = Tkinter.Tk()
img = Tkinter.PhotoImage(file='c:/temp/spam.gif')
print img.height(), img.width()
# 32 64
}}}
This is limiting, since {{{PhotoImage}}} only supports GIF and PGM/PPM image formats. It also has the {{{BitmapImage}}} class, but it only supports monochrome (two-color) images in the X11 bitmap format.
----
For more robust functionality (and a wider range of file formats), you can use the (external lib) [[Python Image Library's|http://www.pythonware.com/products/pil/]] (PIL) [[Image module|http://www.pythonware.com/library/pil/handbook/image.htm]]:
{{{
from PIL import Image
im = Image.open("spam.jpg")
width, height = im.size
}}}
----
Also, ~PySide: This accepts many other file types.
{{{
import PySide.QtGui as QtGui
qir = QtGui.QImageReader("c:/temp/spam.gif")
print qir.size()
PySide.QtCore.QSize(2048, 2048)
width = qir.width()
height = qir.height()
}}}
----
If you have Imagemagick installed:
{{{
stdout, stder = subprocess.Popen([magickExe, "identify", "-format", "%[fx:w] %[fx:h]", image],
stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
width, height = [int(val) for val in stdout.decode().split(" ")]
}}}
I have yet to find a ''built-in\platform-independent'' way of doing this (at the same time). But below are a few options.
----
If you have the module [[win32api|http://python.net/crew/mhammond/win32/]] installed you can query it this way on a ''Windows'' box:
{{{
from win32api import GetSystemMetrics
res = ( GetSystemMetrics(0), GetSystemMetrics(1) )
}}}
----
If you have [[PyGame|http://www.pygame.org]] installed, you can use it as a ''platform-independent'' query:
{{{
import pygame
info = pygame.display.Info()
res = (info.current_w, info.current_h)
print res
# (1920, 1200)
}}}
Most of this I learned from the [[Raspberry Pi Users Guide||http://www.amazon.com/Raspberry-User-Guide-Gareth-Halfacree/dp/111846446X]].
!!! ~RPi.GPIO Installation
The Python library that book recommends to access the GPIO ports is:
*http://code.google.com/p/raspberry-gpio-python/
*http://pypi.python.org/pypi/RPi.GPIO
To install it on your Pi, in a Pi terminal, cd to your home directory. Then (the below files are based on the current ones at the time of authoring. Check the site for the latest version).
Documentation: There does't appear to be much (at least, none that I can find). However, a [[test.py|http://code.google.com/p/raspberry-gpio-python/source/browse/test/test.py]] module is included, showing much of its functionality.
{{{
wget http://raspberry-gpio-python.googlecode.com/files/RPi.GPIO-0.4.1a.tar.gz
tar xvzf RPi.GPIO-0.4.1a.tar.gz
cd RPi.GPIO-0.4.1a
sudo python setup.py
}}}
!!!Pin Layout
The Pi has 26 pins, in two rows. While they are numbered 1-26, they can be indexed two different ways: A, Via these numbers, or B, via a different set of 'GPIO' numbers (discussed below).
http://elinux.org/RPi_Low-level_peripherals : Includes a good descriptive pic, illustrating the 'GPIO numbering' indexing.
You can also do a [[Google image search|https://www.google.com/search?q=raspberry+pi+gpio+pins+diagram&source=lnms&tbm=isch&sa=X&ei=iLUxU8vfNMi8oQThyoKIBA&ved=0CAgQ_AUoAQ&biw=1143&bih=1046]] to find a plethora of diagrams.
If you hold the pi so you can read all the words properly:
| 2 : 5v | 4 : DNC | 6 : grnd | 8 : GPIO 14 (UART TXD) |10 : GPIO 15 (UART RXD) | @@12 :GPIO 18@@ | 14 : DNC | @@16 : GPIO 23@@ | @@18 :GPIO 24@@ | 20 : DNC | @@22 : GPIO 25@@ | 24 : GPIO 8 (SPI 0) | 26 : GPIO 7 (SPI 1) |
| 1 : 3v3 | 3 : GPIO 0 (I^^2^^C SDA) | 5 :GPIO 1 (I^^2^^C SCL) | 7 : GPIO 4 (~GPCLK0) | 9 : DNC | @@11 : GPIO 17@@ | @@13 : GPIO 21@@ | @@15 : GPIO 22@@ | 17 : DNC | 19 : GPIO 10 (SPI MOSI) | 21 : GPIO 9 (SPI MISO) | 23 : GPIO 11 (SPI SLCK) | 25 : DNC |
Anything with 'DNC' means 'do not connect' (according to the book). Anything @@highlighted yellow@@ are the pins truly 'general purpose'. and available for arbitrary usage. The other pins are used for different communication protocols.
!!!Pin Power
*Incoming Power:
**+5v over USB. ~PoE (Power over Ethernet) isn't yet possible.
*GPIO Pin Info:
**+3.3v out, 50mA max
**The +5v pins, It's 1A max minus the boards own usage (700ma). This equates to: 1000 mA - 700 mA -> max current draw: 300 mA
Internal pull-up and pull-down resistors can be set on pins:
{{{
GPIO.setup(11, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(11, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(11, GPIO.IN, pull_up_down=GPIO.PUD_OFF) # The default
}}}
!!!Pin Access
The {{{RPi.GPIO}}} library gives easy access to the {{{GPIO}}} pins. That being said, I had a bit of confusion initially based on some code changes that went in after the "Raspberry Pi Users Guide" was published. Namely, how you know which method you're using to access the pins, whether the board-pin layout, or the 'GPIO numbers' layout?
Long story short: If you want to use the pin numbers as ordered on the Pi itself, you need to call to this function to set it up:
{{{
import RPi.GPIO as GPIO
# Set to use physical board pin nums, rather than GPIO nums:
GPIO.setmode(GPIO.BOARD)
}}}
If you want to use the 'GPIO' pin numbers, call using this arg instead:
{{{
import RPi.GPIO as GPIO
# Set to use GPIO nums, rather than physical board nums:
GPIO.setmode(GPIO.BCM)
}}}
And what is 'BCM' anyway? (I think it's possibly an abbreviation for the "~BroadCoM" chipset it uses).
If you're using some type of GPIO header breakout-board like Adafruit's [[Pi Cobbler|http://learn.adafruit.com/adafruit-pi-cobbler-kit/overview]], you'll be addressing via the GPIO numbers, rather than the physical board pin numbers.
!!!Examples
Here's a simple example (I have running on the Pi as I type, via Adafruit's [[Raspberry Pi's WebIDE|http://learn.adafruit.com/webide]] * the Pi Cobbler) showcasing these concepts.
{{{
#!/user/bin/env python
"""
gpiooutput.py
Modified from pg 195 of "Raspberry Pi Users Guide"
Make a LED flash on\off.
Hardware Setup:
* LED+ lead hooked to GPIO 17 (board pin 11)
* LED- lead connected to resistor.
* Resistor connected to ground (board pin 6)
"""
import time
import RPi.GPIO as GPIO
# This is the GPIO number. The actual board pin is number 11.
PINOUT = 17
def main():
GPIO.setmode(GPIO.BCM) # Set to use GPIO nums, rather than physical board nums
GPIO.setup(PINOUT, GPIO.OUT)
print "Blink begins! Press ctrl+c to exit"
try:
i = 1
while True:
GPIO.output(PINOUT, True)
print "Blink %s ON!!"%i
time.sleep(2)
GPIO.output(PINOUT, False)
print "Blink %s OFF!!"%i
time.sleep(2)
i += 1
except KeyboardInterrupt:
GPIO.output(PINOUT, False)
print "\nBlink DONE!"
return
if __name__ == "__main__":
main()
}}}
Found here: http://nodebox.net/code/index.php/Math
Source:
*[[distance|Location of a point based on angle and distance]]
*[[angle|Angle between two points]]
*[[coordinates|Location of a point based on angle and distance]]
{{{
def reflect(x0, y0, x1, y1, d=1.0, a=180):
d *= distance(x0, y0, x1, y1)
a += angle(x0, y0, x1, y1)
x, y = coordinates(x0, y0, d, a)
return x, y
}}}
[[Regular Expression Syntax|http://www.python.org/doc/2.4.2/lib/re-syntax.html]]
[[Regular Expression HOWTO|http://docs.python.org/howto/regex.html]]
http://www.doughellmann.com/PyMOTW/re/
http://tartley.com/wp-content/uploads/2011/10/cheatsheet.pdf
----
* {{{.}}} = period, represents any character. For example, if you wanted to do a normal 'wildcard' match of {{{"spam*eggs"}}} (to match any number of chars between the two words), you'd do it as {{{"spam.*eggs"}}}, following the rules for {{{*}}} below.
* {{{^}}} = Anchor RE to start of line.
* {{{$}}} = Anchor RE to end of line.
* {{{\d}}} = Matches any decimal digit; this is equivalent to the class [0-9].
* {{{\D}}} = Matches any non-digit character; this is equivalent to the class [^0-9].
* {{{\s}}} = Matches any whitespace character; this is equivalent to the class [ \t\n\r\f\v].
* {{{\S}}} = Matches any non-whitespace character; this is equivalent to the class [^ \t\n\r\f\v].
* {{{\w}}} = Matches any alphanumeric character; this is equivalent to the class [a-zA-Z0-9_].
* {{{\W}}} =Matches any non-alphanumeric character; this is equivalent to the class [^a-zA-Z0-9_].
* {{{*}}} = Causes the resulting RE to match 0 or more repetitions of the preceding RE, as many repetitions as are possible. ab* will match ‘a’, ‘ab’, or ‘a’ followed by any number of ‘b’s.
* {{{+}}} = Causes the resulting RE to match 1 or more repetitions of the preceding RE. ab+ will match ‘a’ followed by any non-zero number of ‘b’s; it will not match just ‘a’.
* {{{?}}} = Causes the resulting RE to match 0 or 1 repetitions of the preceding RE. ab? will match either ‘a’ or ‘ab’.
----
{{{
import re
}}}
{{{
# re.match()
# Determine if the RE matches at the beginning of the string.
# This returns an object, and it's mainly good for truth testing.
foo = "new_stuff"
if re.match("new", foo):
print "yes"
# yes
}}}
{{{
# Scan through a string, looking for any location where this RE matches.
re.search()
# Find all substrings where the RE matches, and returns them as a list.
re.findall()
# Find all substrings where the RE matches, and returns them as an iterator.
re.finditer()
}}}
----
If you're trying to match a sub-string in a longer string, but you want to match even if the case doesn't:
<<tiddler [[How can I match strings irregardless of case?]]>>
----
Given a multiline string, extract just certain data from it:
{{{
multiline = '''data 0 -1 "bob"
data 1 0 "john"
data 2 0 "stan"
data 3 0 "larry"
data 4 1 "frank"
data 5 1 "henry"
'''
data = [item.replace('"', '') for item in re.findall('".*"' , multiline)]
print data
# ['bob', 'john', 'stan', 'larry', 'frank', 'henry']
}}}
----
Extract the last sequence of integer numbers from a string:
{{{
myStr = 'pPlane1.vtx[60]'
pattern = r'\d+'
vid = int(re.findall(pattern, myStr)[-1])
# 60
}}}
{{{
>>> if re.search("word", "is there a word in here?"):
>>> print "found match!"
found match!
}}}
{{{
# note that .group() only works if there is a match
>>> m = re.match("ab", "abcd").group()
>>> print m
'ab'
}}}
{{{
>>> re.findall(r'bf[a-z]*', 'which foot or hand fell fastest')
['foot', 'fell', 'fastest']
}}}
{{{
>>> re.sub(r'(b[a-z]+) 1', r'1', 'cat in the the hat')
'cat in the hat'
}}}
{{{
>>> fooRe = re.compile(r'foo.*?((.*?))')
>>> fooRe.search('foo(bar)').group(1)
'bar'
>>> fooRe.search('This is a foo bar baz blah blah (bar)').group(1)
'bar'
}}}
{{{
word = "find the number at the end 23"
print re.findall('[0-9]+$', word)
# ['23']
}}}
Here, we want to see if a line has some specfic text inside some brackets and quotes: If the line contains this string: {{{' [ "*" ] '}}} with anything represented by the *, then there will be a positive sized list.
{{{
line = '"someText" [ "someMoreText" ]'
exp = '\[ ".*" \]'
print re.findall(exp , line)
['[ "someMoreText" ]']
}}}
----
Find all the words after some other word. In this case, find everything after {{{_something_}}} including {{{_something_}}}
{{{
fName = "a_b_c_d-1_something_1234_62"
regex = r'(_something_\S+)$'
match = re.findall(regex, fName, re.IGNORECASE)
print match
['_something_1234_62']
}}}
This will find everything after {{{_something_}}}, but not include it:
{{{
fName = "a_b_c_d-1_something_1234_62"
regex = r'_something_(\S+)$'
match = re.findall(regex, fName, re.IGNORECASE)
print match
['1234_62']
}}}
----
This doesn't use the {{{re}}} module, but its so similar I think it should be listed.
<<tiddler [[How can I find the 'prefix' of a string?]]>>
*2D:
**[[pymunk|http://code.google.com/p/pymunk/]] is a wrapper around [[Chipmunk|http://code.google.com/p/chipmunk-physics/]] : a "2D rigid body physics library in C"
**[[pybox2d|http://code.google.com/p/pybox2d/]] is a wrapper around [[Box2D|http://www.box2d.org/]] : a "2D rigid body physics library in C++"
***[[Box2D Wiki for pybox2d|http://www.box2d.org/wiki/index.php?title=Box2D_with_Python]]
*3D
**[[PyODE|http://pyode.sourceforge.net/]] is a set of open-source Python bindings for the [[Open Dynamics Engine|http://ode.org/]]
**[[cgkit|http://cgkit.sourceforge.net/]] has a wrapper around the [[Open Dynamics Engine|http://ode.org/]] in its ~ODEDynamics ([[docs|http://cgkit.sourceforge.net/doc2/odedynamics.html]]) module.
**[[VPython|http://vpython.org]]
***Example videos: http://showmedo.com/videotutorials/series?name=pythonthompsonvpythonseries
Notes and code examples:
*http://panela.blog-city.com/ann_coreit__helper_to_throw_python_code_onto_cores.htm
**http://github.com/mattharrison/coreit
**http://github.com/mattharrison/coreit/blob/master/coreit.py
https://www.sqlitetutorial.net/sqlite-python/ <-- Great Python tutorial.
~PySQLite is a part of the Python Standard library since Python version 2.5
!Open the DB in a sqlite3 shell:
I've found on my local PC, it's installed here, but who knows how wide-spread this is:
{{{
C:\Microsoft\AndroidSDK\25\platform-tools\sqlite3.exe
}}}
If not:
https://www.sqlite.org/download.html
Why do this? So you can test if your Python-related updates actually work before you author all the code in Python to check for them ;)
!Common DB command-line query commands:
{{{
> sqlite3 c:\some\path\to\my.db
}}}
!!Print all the table names:
{{{
> .tables
}}}
!!Print contents for a specific table:
{{{
> .header on
> .mode column
> SELECT * FROM myTableName
}}}
!!Print contents for a specific table based on some criteria:
{{{
> .header on
> .mode column
> SELECT * FROM myTableName WHERE id = 2;
}}}
Where, 'id' could be the name of any column in the table.
Following the tutorial here:
https://www.sqlitetutorial.net/sqlite-python/
As a complete noob, I authored the below code which works a-ok. Probably better ways to do it, but for the time being, an example:
In this example (Python 2.7), we make a database with a single table, and update 'names' in it.
{{{
# myDatabase.py
from __future__ import print_function
import os
import sqlite3
#----------------------------
DB_DIR = r"C:\some\dir\to\the\database\sqlite"
DB_FILE = "myAwesomeDatabase.db"
class DB(object):
"""
An object that will connect to our database and provide methods
for interaction. Can call to directly, or via the 'with' statement.
"""
table = "myTableName"
@staticmethod
def getDbPath():
"""
Return the path to this database.
"""
if not os.path.isdir(DB_DIR):
os.makedirs(DB_DIR)
dbPath = os.path.join(DB_DIR, DB_FILE)
return dbPath
def __init__(self):
"""
Init the database.
"""
self.dbPath = DB.getDbPath()
# Will create the db if it doesn't exist.
self.conn = sqlite3.connect(self.dbPath)
self.cursor = self.conn.cursor()
self.createTable()
def __del__(self):
"""
Shut down out DB connection when this object is destroyed. Happens whenever
it goes out of scope, or del is called on it.
"""
self.close()
def __str__(self):
"""
Return the string path to the db file.
"""
return self.dbPath
def __enter__(self):
"""
Setup to be a context manager / 'with' statement.
"""
return self
def __exit__(self, exc_type, exc_value, traceback):
"""
Setup to be a context manager / 'with' statement.
Called when the contex is exited.
exc_type : If there is an Exception, the type. Otherwise None
exec_value : If there is an Exception, the value. Otherwise None
traceback : If there is an Exception, the traceback. Otherwise None
return : True \ False : If False, and there was an exception, re-raise the
exception. If True and there was an exception, handle the exception
silently.
"""
self.close()
return False
#-------------------
# DB setup & housekeeping.
def createTable(self):
"""
Create a 'table' for this db, which is basically the header info for each column.
Only needs to be ran when the DB is initial created, but running it again
is harmless.
Set the 'name' field to be 'unique', so that there can't be any dupes of it
in the DB.
Parameters:
conn : Connection instance.
table : string : Default global TABLE : The 'table' name to create.
"""
sql = """ CREATE TABLE IF NOT EXISTS %s (
id integer PRIMARY KEY,
name text NOT NULL,
UNIQUE(name)
); """%DB.table
self.cursor.execute(sql)
def close(self):
"""
Close the connection to this database. Can be called to multiple times
harmlessly.
"""
self.conn.close()
#-------------------
# DB Actions:
def insertNames(self, names):
"""
Insert the provided 'names' into the database. If any are dupliactes, ignore.
Parameters:
name : string/list : List of string names to insert, or a single string name.
"""
if not isinstance(names, (list,tuple)):
names = [names]
# If 'OR IGNORE' is left out and and a dupe is added, and exception is raised.
for name in names:
sql = ''' INSERT OR IGNORE INTO %s(name)
VALUES(?) '''%DB.table
self.cursor.execute(sql, (name,))
def deleteNames(self, names):
"""
Delete the given 'data' (aka, 'name') from the database.
Parameters:
names : string/list : The names to delete. Which in this case is the 'name'.
"""
if not isinstance(names, (list,tuple)):
names = [names]
for name in names:
sql = 'DELETE FROM %s WHERE name=?'%(DB.table)
self.cursor.execute(sql, (name,))
self.conn.commit()
def deleteAllNames(self):
"""
Delete/clear all data from the DB.
"""
sql = 'DELETE FROM %s'%DB.table
self.cursor.execute(sql)
self.conn.commit()
def deleteTable(self):
"""
Delete the table from the database.
"""
try:
self.cursor.execute('DROP TABLE %s;'%DB.table)
self.conn.commit()
except:
# Doesn't exist, ignore. Probably a better way, I'm a noob.
pass
def tableExists(self):
"""
Return bool if the primary table exists.
"""
sql = "SELECT name FROM sqlite_master WHERE type='table' AND name='%s';"%DB.table
self.cursor.execute(sql)
data = self.cursor.fetchall()
if data:
return True
else:
return False
def getNames(self):
"""
Query all the data in the DB.
Return : tuple : Each item is a sub-tuple of (id, 'name').
"""
self.cursor.execute("SELECT * FROM %s"%DB.table)
return self.cursor.fetchall()
def getConnection(self):
"""
Return the sqlite3.Connection instance for this database.
https://docs.python.org/2/library/sqlite3.html#sqlite3.Connection
"""
return self.conn
def getCursor(self):
"""
Return the sqlite3.Cursor instance for this database.
https://docs.python.org/2/library/sqlite3.html#cursor-objects
"""
return self.cursor
#--------------------------
# Debug
if __name__ == "__main__":
with DB() as db:
print("My DB:", db)
print("Inserting names:")
# Add an extra duplicate 'Sad': Only one should be added.
names = ("Happy", "Sad", "Spam", "Eggs", "Sad")
print("Adding Names:", names)
db.insertNames(names)
allNames = db.getNames()
print("DATA QUERY:")
for an in allNames:
print("\t", an)
print("Deleting 'Sad'")
db.deleteNames("Sad")
allNames = db.getNames()
print("DATA QUERY:")
for an in allNames:
print("\t", an)
print("Deleting all names...")
db.deleteAllNames()
allNames = db.getNames()
print("DATA QUERY:")
if allNames:
for ad in allNames:
print("\t", ad)
else:
print("\tNo Data in the DB")
print("Deleting '%s' table"%DB.table)
db.deleteTable()
tableExist = db.tableExists()
print("'%s' table exist?"%DB.table, tableExist)
# Not needed here, since the context manager handles/closes it.
#db.close()
}}}
!pickle \ cPickle
Update: {{{cPickle}}} doesn't exist in Python3 as an import: It's now an implementation detail. Just use {{{import pickle}}}.
The pickle module implements a fundamental, but powerful algorithm for serializing and de-serializing a Python object structure. “Pickling” is the process whereby a Python object hierarchy is converted into a byte stream, and “unpickling” is the inverse operation, whereby a byte stream is converted back into an object hierarchy. Pickling (and unpickling) is alternatively known as “serialization”, “marshalling,” or “flattening”, however, to avoid confusion, the terms used here are “pickling” and “unpickling”.
*http://docs.python.org/library/pickle.html
*http://docs.python.org/library/pickle.html#module-cPickle
*[[What can be pickled, and unpickled?|http://docs.python.org/library/pickle.html#what-can-be-pickled-and-unpickled]]
>The (Python2, not 3) pickle module has an optimized cousin called the cPickle module. As its name implies, cPickle is written in C, so it can be up to 1000 times faster than pickle. However it does not support subclassing of the Pickler() and Unpickler() classes, because in cPickle these are functions, not classes. Most applications have no need for this functionality, and can benefit from the improved performance of cPickle. Other than that, the interfaces of the two modules are nearly identical; the common interface is described in this manual and differences are pointed out where necessary.
Simple Example:
{{{
import os
import pickle
# Create a temp filename to store our data in:
dataFile = os.path.join(os.getenv("TMP"), "pyData.txt")
# in my case, it lives here (in Vista):
# C:\Users\<USERNAME>\AppData\Local\Temp\pyData.txt
# Make dictionary of some data to store:
data = {"first":1, "second":2}
# Write/pickle/serialize/dump our data to disk:
with open(dataFile, 'wb') as outf:
# The 'protocol' has been set to 2, which controls how return
# characters are stored. Use it. More below...
pickle.dump(data, outf, 2)
# or this, I'm told it may be better/safer, but currently, it's still just 2 for me:
# pickle.dump(data, outf, pickle.HIGHEST_PROTOCOL)
# Read/unpickle/unserialize/load the data:
with open(dataFile, 'rb') as inf:
loadedData = pickle.load(inf)
print(loadedData)
}}}
{{{
{'second': 2, 'first': 1}
}}}
@@NOTE@@ : Sometimes, even with 'protocol' set to 2, if you add this data to P4, P4 can mangle the newlines: p4 decides with the byte order marker if a file is binary or ascii, and sometimes it gets this wrong on pickled data. To be sure, in P4 add a typemap change so all files of your extension are treated are treated as binary.
!shelve
A “shelf” is a persistent, dictionary-like object. The difference with “dbm” databases is that the values (not the keys!) in a shelf can be essentially arbitrary Python objects — anything that the pickle module can handle. This includes most class instances, recursive data types, and objects containing lots of shared sub-objects. The keys are ordinary strings.
*http://docs.python.org/library/shelve.html
*http://inventwithpython.com/blog/2012/05/03/implement-a-save-game-feature-in-python-with-the-shelve-module/
!marshal
This module contains functions that can read and write Python values in a binary format. The format is specific to Python, but independent of machine architecture issues (e.g., you can write a Python value to a file on a PC, transport the file to a Sun, and read it back there). Details of the format are undocumented on purpose; it may change between Python versions (although it rarely does).
This is not a general “persistence” module. For general persistence and transfer of Python objects through RPC calls, see the modules pickle and shelve. The marshal module exists mainly to support reading and writing the “pseudo-compiled” code for Python modules of .pyc files. Therefore, the Python maintainers reserve the right to modify the marshal format in backward incompatible ways should the need arise. If you’re serializing and de-serializing Python objects, use the pickle module instead – the performance is comparable, version independence is guaranteed, and pickle supports a substantially wider range of objects than marshal.
*http://docs.python.org/library/marshal.html
The bulk of these notes are pulled from [[Programming Computer Vision With Python|http://shop.oreilly.com/product/0636920022923.do]]
----
Docs, etc:
http://www.scipy.org/
http://docs.scipy.org/doc/scipy/reference/
----
~SciPy builds on ~NumPy and extends it.
----
Blur an image, via image convolution:
{{{
from PIL import Image
from numpy import array
from scipy.ndimage import filters
im = array(Image.open(myImage).convert('L'))
imBlur = filters.gaussian_filter(im, 5)
}}}
----
Open some [[Matlab|http://www.mathworks.com/products/matlab/]] {{{.mat}}} data:
{{{
import scipy
data = scipy.io.loadmat('test.mat')
}}}
{{{data}}} is a {{{dict}}} with keys corresponding to variable names saved in the {{{.mat}}} file.
----
Save [[Matlab|http://www.mathworks.com/products/matlab/]] {{{.mat}}} data:
{{{
import scipy
data = {}
data['x'] = 23
scipy.io.savemat('test.mat', data)
}}}
----
Save a Numpy array as an image:
{{{
import scipy
scipy.misc.imsave("test.jpg", myArray)
}}}
You can also save out a "Lena" grayscale test image, 512x512:
{{{
lena = scipy.misc.lena()
}}}
https://semver.org/
Less a Python thing, more of a 'how to version your code thing'. But worth soring here.
"1.5.7":
* 1 : Major version
* 5 : Minor version
* 7 : Patch
Per their docs:
# {{{MAJOR}}} version when you make incompatible API changes,
# {{{MINOR}}} version when you add functionality in a backwards compatible manner, and
# {{{PATCH}}} version when you make backwards compatible bug fixes.
I recently ran across this post that spells it out pretty nicely:
http://www.blog.pythonlibrary.org/2010/05/14/how-to-send-email-with-python/
serial port: ~COM-port, or ~RS232
----
Python seems to have no builtin 'serial' module\package. But searching the Python docs here:
http://docs.python.org/3.1/faq/library.html#how-do-i-access-the-serial-rs232-port
Leads one to ''pySerial'': http://pyserial.sourceforge.net/
pySerial Class docs: http://pyserial.sourceforge.net/pyserial_api.html#classes
----
Example ''sending'' data to the serial port (example pulled from the [[Arduino docs|http://www.arduino.cc/playground/Interfacing/Python]]).
It should be noted that this only works properly when excuted from an interactive shell... it fails to work when in a module. I'm trying to figure out why...
{{{
>>> import serial
>>> PORT = 'COM4'
>>> ser = serial.Serial(PORT)
>>> ser.write('5')
>>> ser.close()
}}}
----
[[Video from PyCon 2012|http://www.youtube.com/watch?v=54XwSUC8klI&feature=player_embedded#!]] by Peter Kropf illustrating how to have Python communicate over a serial port to control an Arduino.
----
Example with ''capturing'' serial data, in this case sent from an [[Arduino|http://www.arduino.cc/]] microcontroller.
{{{
import serial
ARDUINO = "COM4"
def main():
ser = serial.Serial(ARDUINO, timeout=1)
prevVal = None
while 1:
# Read the serial value
ser.flushInput()
serialValue = ser.readline().strip()
# Catch any bad serial data:
try:
if serialValue != prevVal:
# Print the value if it differs from the prevVal:
print "New Val: ", serialValue
prevVal = serialValue
except ValueError:
pass
ser.close()
if __name__ == '__main__':
main()
}}}
If you run this from a command prompt, presuming the Arduino is broadcasting data, any //new// data will be printed to the display.
If you want to see more examples of this using the Arduino, including code running in [[Pygame|http://www.pygame.org]] and [[Processing|http://www.processing.org/]], you can check my blog here:
http://www.akeric.com/blog/?p=1015
----
Finding Serial Ports: http://pyserial.sourceforge.net/examples.html#finding-serial-ports
----
!!!Notes from the web:
http://ayaz.wordpress.com/2007/06/11/serial-port-communication-on-slackware-using-pyserial/
<<<
You can use two features of pySerial to your advantage. One is the
timeout parameter that you specify when creating a serial.Serial() object. If you set timeout=None, and call method read() or readline(), pySerial will wait forever until there is data in its receive buffer. The second feature is the inWaiting() method. It tells you how many characters are waiting in the receive buffer to be read.
If you set timeout=None, run a loop, but call readline() once within the loop, your program will block until there are characters in the receive buffer. You can, then, do what you want with the data received. Or, you could loop around a call to inWaiting(), only calling read() or readline() whenever there are characters waiting in the receive buffer.
<<<
----
http://eli.thegreenplace.net/category/programming/serial-port/
many subjects listed
----
<<closeAll>><<permaview>><<newTiddler>><<saveChanges>><<tiddler TspotSidebar>><<slider chkSliderOptionsPanel OptionsPanel 'options »' 'Change TiddlyWiki advanced options'>>
<<tabs txtMainTab Tags 'All tags' TabTags >>
<<tabs txtMainTab Dummy Dummy TabDummy Timeline Timeline TabTimeline All 'All tiddlers' TabAll More 'More lists' TabMore>>
Modified version of [[this code|http://sentdex.com/sentiment-analysisbig-data-and-python-tutorials-algorithmic-trading/python-tutorial-on-threading/]] shows how to do simple multi-threading. Note that an 'event' is created, that will block the execution of {{{runRandomly}}} until the first time {{{runLessOften}}} is executed.
{{{
import threading
from time import sleep
import random
# Create an event that can be used to block other threads.
blocker = threading.Event()
def runOften():
"""
Run every 2 seconds.
"""
while True:
sleep(2)
print "Often Runs : 2 sec"
def runLessOften():
"""
Run every 5 seconds. Set blocker event on\off alternatly each time its ran.
"""
while True:
sleep(5)
print "Runs less often 5 sec"
if not blocker.isSet():
blocker.set()
print "Event : NOT BLOCKING"
else:
blocker.clear()
print "Event : BLOCKING"
def runRandomly():
"""
Won't start running until the blocker event is set. Then runs randomly at
less than second itervals.
"""
while True:
# Block here until the blocker event is set:
blocker.wait()
rnd = random.random()
sleep(rnd)
print "Fast and Random : %s sec"%rnd
def main():
try:
threading.Thread(target=runOften).start()
threading.Thread(target=runLessOften).start()
threading.Thread(target=runRandomly).start()
except Exception, e:
print e
if __name__ == "__main__":
main()
}}}
A chunk of what it spits out. You can see that once "Run Less often" executes, it unblocks the random prints:
{{{
Often Runs : 2 sec
Often Runs : 2 sec
Runs less often 5 sec
Fast and Random : 0.338409410883 sec
Often Runs : 2 sec
Fast and Random : 0.89308248495 sec
Fast and Random : 0.28363599317 sec
Fast and Random : 0.873124875804 sec
}}}
[[threading|http://docs.python.org/2/library/threading.html]] module docs.
Found this blog post [[here|http://ruslanspivak.com/2011/03/30/simple-http-server-from-the-command-line/]], reposted below:
<<<
I’ve been using this small Python gem for couple years now and it really comes in handy when you need a quick web server running without setting up nginx or apache or what have you.
Just open up a terminal and type:
{{{
$ python -m SimpleHTTPServer
Serving HTTP on 0.0.0.0 port 8000 ...
}}}
Now check it in your browser: http://localhost:8000/
You can also change port the server is listening on:
{{{
$ python -m SimpleHTTPServer 7070
Serving HTTP on 0.0.0.0 port 7070 ...
}}}
<<<
Since I (currently) do zero web\server stuff with Python, this is pretty fascinating to me. When I open my browser, I see a mirror of this dir tree (from Windows 7):
{{{
C:\Users\<userName>
}}}
Whenever I need to write a recursive function I always tie my brain in a knot trying to figure it out, when it's really not that hard.
Simple example below. Its a silly example, because it's redoing what {{{os.walk}}} does, but it does show recursion.
{{{
import os
startDir = r'c:\temp'
# This will be list that holds all the stuff we find:
dirs = [startDir]
# Loop over our ever expanding list:
for d in dirs:
walker = os.walk(d)
subdirList = walker.next()[1]
if len(subdirList):
subdirs = [os.path.join(d, sd) for sd in subdirList]
# Extend our list with the new stuff we find, which will
# be iterated over in future loops:
dirs.extend(subdirs)
}}}
{{{
print dirs
['c:\\temp', 'c:\\temp\\foo', 'c:\\temp\\test', 'c:\\temp\\foo\\boo']
}}}
notes on learning the language
[img[python wiki|http://farm4.static.flickr.com/3026/2514848314_335cab2127.jpg?v=0][Welcome]]python wiki
A place to collect sorting tips I've picked up.
*[[How can I sort a dictionary by its values?]]
*[[How can I sort strings with non-padded numbers on the end?]]
*[[How can I sort by my own rules?]]
----
Some examples from:
http://docs.python.org/library/operator.html#operator.itemgetter
{{{
from operator import itemgetter
inventory = [('apple', 3), ('banana', 2), ('pear', 5), ('orange', 1)]
getcount = itemgetter(1)
map(getcount, inventory)
# [3, 2, 5, 1]
sorted(inventory, key=getcount)
# [('orange', 1), ('banana', 2), ('apple', 3), ('pear', 5)]
}}}
http://docs.python.org/library/stdtypes.html#special-attributes
{{{
__dict__
__methods__
__members__
__class__
__bases__
__name__
}}}
Also:
{{{
__file__
}}}
A special member of every module is {{{__dict__}}}. This is the dictionary containing the module's symbol table.
http://docs.python.org/lib/typesmodules.html
----
Also see:
*[[Special Modules]]
*[[Understanding __dict__]]
I'm starting another section here:
[[Operator Overloading]]
But I'm keeping this tiddler around until that one is updated.
----
''Official link#1: http://www.python.org/doc/2.3.5/ref/specialnames.html''
''Official link#2: http://docs.python.org/ref/specialnames.html''
Link#3: http://www2.lib.uchicago.edu/keith/courses/python/class/5/
Link#4: http://www.siafoo.net/article/57 (good reference)
In learning Python, I constantly see names with 'double-underscores' on either side of them. The top link is a good overview of all the 'special methods' relative to [[Class]]es. Some specific notes are below, as I interact with them.
----
{{{
__init__
}}}
This is a 'constructor method' or 'initialization function' for a [[Class]]. Usually written like:
{{{
def __init__(self, someArg):
someAttr = someArg
}}}
----
{{{
__str__
}}}
When you '{{{print}}}' a [[Class]], it usually spits out something like this:
{{{
f = Foo() # make a f object
print f
<__main__.Foo object at 0x00A0Ba90>
}}}
But by defining a {{{__str__}}} method in your [[Class]], you can have it print something else:
{{{
def __str__(self):
rep = "This is a Foo object, yay!"
return rep
}}}
In general, the string returned by {{{__str__}}} is meant for the user of an application to see, while the string returned by {{{__repr__}}} (below) is meant for the programmer to see.
----
{{{
__del__
}}}
A {{{__del__}}} method is called when an object is deleted, which is when the garbage collector decides that their are no more references to an object
{{{
def __del__(self):
#code
}}}
----
{{{
__repr__
}}}
A {{{__repr__}}} method takes exactly one parameter, self, and must return a string. This string is intended to be a representation of the object (This is sometimes called the 'reproduction string'), suitable for display to the programmer, for instance when working in the interactive interpreter. {{{__repr__}}} will be called anytime the builtin {{{repr}}} function is applied to an object; this function is also called when the backquote operator is used. See {{{__str__}}} above. See Python docs on [[Emulating container types|http://docs.python.org/ref/sequence-types.html]].
----
----
http://docs.python.org/lib/module-builtin.html:
Provides direct access to all `built-in' identifiers of Python
{{{
__builtin__
}}}
----
http://docs.python.org/lib/module-main.html
Represents the (otherwise anonymous) scope in which the interpreter's main program executes
{{{
__main__
}}}
It is the top level [[namespace]] for the current execution.
----
http://docs.python.org/lib/module-future.html
{{{
__future__
}}}
----
Also see:
*[[Special Attributes]]
I had need of a solution, found one over on [[Stack Overflow|http://stackoverflow.com/questions/3149440/python-splitting-list-based-on-missing-numbers-in-a-sequence]], some of it is pasted below:
{{{
>>> from operator import itemgetter
>>> from itertools import *
>>> seq2 = [1, 2, 4, 5, 6, 8, 9, 10]
>>> chunks = []
>>> for k, g in groupby(enumerate(seq2), lambda (i,x):i-x):
... chunks.append(map(itemgetter(1), g))
...
>>> print chunks
[[1, 2], [4, 5, 6], [8, 9, 10]]
}}}
Or with a list comprehension:
{{{
>>> chunks = [map(itemgetter(1), g) for k, g in groupby(enumerate(seq2), lambda (i,x):i-x)]
[[1, 2], [4, 5, 6], [8, 9, 10]]
}}}
How slick is that?
http://docs.python.org/library/itertools.html#itertools.groupby
http://docs.python.org/library/operator.html#operator.itemgetter
Obviously Python comes with a {{{sqrt}}} function in the {{{math}}} module. But what if you want to 'make your own'?
The below example, and descriptions for the code can be found here: http://radiantbytes.com/books/python-latex/src/chap9.html
{{{
def abs(val):
#Could just import abs from the math module of course.
if val < 0:
val *= -1
return val
def average(a, b):
return (a + b) / 2.0
def improve(guess, x):
return average(guess, x/guess)
def good_enough(guess, x):
d = abs(guess*guess - x)
return (d < 0.001)
def square_root(guess, x):
while(not good_enough(guess, x)):
guess = improve(guess, x)
return guess
def sqrt(x):
r = square_root(1, x)
return r
}}}
Statements are one or more lines of Python code ''that give Python orders''.
*[[Simple Statements|http://docs.python.org/reference/simple_stmts.html]]
*[[Compound Statements|http://docs.python.org/reference/compound_stmts.html]]
Statements can span multiple lines with the 'line continuation character' '{{{\}}}' (but I hear that's gone out of flavor these days):
{{{
# single line:
print "happy"
#multi-line:
print\
"happy"
}}}
Statements are made up of two parts, the ''command'', and the ''expression''. Given the following example:
{{{
print 2+3
}}}
*The ''command'' is {{{print}}}. Tells the computer to take action.
*The ''expression'' is the string {{{2+3}}}. It is what the command acts upon. An expression is a piece of syntax which can be evaluated to some value. {{{2+3}}} is an expression, since it evaluates to {{{5}}}.
----
This is called an 'assignment statement':
{{{
name = "juffo wup"
# we are assigning the value on the right to the variable on the left
}}}
----
To try and clear things up a bit...
When you 'import something', '{{{import}}}' is a statement:
{{{
import spam
}}}
However, to differentiate this, the {{{import}}} //statement// actually calls to the {{{__import__}}} //function//:
{{{
__import__("spam")
}}}
So in this case, the //statement command// {{{import}}} invokes the {{{__import__}}} //function//, and the //statement expression// {{{spam}}} is passed in as a //string argument// to the //function//.
http://docs.python.org/library/functions.html#staticmethod
Static methods are designed to be invoked through a //class//, and not a instance of that class. In a sense, //methods// are to //objects// what //static methods// are to //classes//. Objects don't see static methods, but classes do. You'll notice when authoring a static method, that you //don't// use {{{self}}} as the first argument, since an instanced object //won't// be passing a reference of itself to the static method. And after you define the 'new static method function', you need to call the {{{staticmethod()}}} function //on it//. This (apparently) 'registers' the function //as// a static method with the class.
{{{
# let's make a static method, previous to Python v2.4:
class FooClass():
total = 0
def status():
print "Total number is", FooClass.total
status = staticmethod(status)
# etc...
}}}
{{{
# let's make a static method via a decorator, Python v2.4 or later:
class FooClass(object):
total = 0
# This is a 'declaration syntax', that describes the function
# that follows. The @ symbol is known as a 'decorator':
@staticmethod
def status():
print "Total number is", FooClass.total
# etc...
}}}
----
Also see:
*[[Class Methods]]
Python supports stream redirection. Not a special feature of Python, it just supports what the OS already provides.
{{{
# spam.py
print "I can print to a file, really!"
}}}
Then, at the prompt:
{{{
% python spam.py > saveFile.txt
}}}
{{{saveFile.txt}}} now has the output from {{{spam.py}}}
Using the {{{print}}} statement in your [[module|Module]] will allow the output of that data to a text file.
This doc gives a pretty good overview of the pros and cons of each:
https://realpython.com/python-f-strings/
To snip some from it
! %-formatting
https://docs.python.org/2.7/library/stdtypes.html#string-formatting-operations
{{{
name = "Eric"
print "Hello, %s."%name
'Hello, Eric.'
}}}
! str.format()
https://docs.python.org/2.7/library/stdtypes.html#str.format
{{{
print "Hello, {}. You are {}.".format(name, age)
'Hello, Eric. You are 74.'
}}}
{{{
print "Hello, {1}. You are {0}.".format(age, name)
'Hello, Eric. You are 74.'
}}}
{{{
person = {'name': 'Eric', 'age': 74}
print "Hello, {name}. You are {age}.".format(name=person['name'], age=person['age'])
'Hello, Eric. You are 74.'
}}}
! f-Strings
Python 3.6+ only!
https://docs.python.org/3/reference/lexical_analysis.html#f-strings
{{{
name = "Eric"
age = 74
f"Hello, {name}. You are {age}."
'Hello, Eric. You are 74.'
}}}
Strings are effectively sequences (tupples) of one character strings. They are //immutable//. Meaning after creation, their individual indicies (characters) can't be changed. They support many list operations though.
{{{
myString = "foo"
# could be similarly written as a tupple:
myTupple = ("f", "o", "o")
print myString[1]
>>> o
print myTupple[1]
>>> o
myString[2] = "g"
# fail: It is an immutable sequence
Traceback (most recent call last):
File "<string>", line 1, in <string>
TypeError: 'str' object does not support item assignment
# BUT, you can *redefine* it successfully:
myString = myString[:-1] + "g"
print myString
>>> fog
}}}
Also see
*[[String methods]]
*[[Sequence Types info|http://docs.python.org/library/stdtypes.html#sequence-types-str-unicode-list-tuple-buffer-xrange]]
{{{
>>> "hello"+"world"
"helloworld" # concatenation
}}}
{{{
>>> "hello"*3
"hellohellohello" # repetition
}}}
{{{
>>> "hello"[0]
"h" # indexing
}}}
{{{
>>> "hello"[-1]
"o" # (from end)
}}}
{{{
>>> "hello"[1:4]
"ell" # slicing
}}}
{{{
>>> len("hello")
5 # size
}}}
{{{
>>> "hello" < "jello"
1 # comparison
}}}
{{{
>>> "e" in "hello"
1 # search
}}}
{{{
"""
multi
line
text
"""
}}}
{{{
>>> mystring = "foo foo"
>>> print mystring.replace("foo", "goo") # search / replace
goo goo
}}}
By default, a string will add a 'newline' character at the end. However, if you want to //suppress// this newline character, you can just add a comma '{{{,}}}' after your string:
{{{
>>> print "no newline",
}}}
----
[[String Formatting|http://docs.python.org/library/stdtypes.html#string-formatting]]
{{{
# very simple example:
>>> foo = "happy"
>>> goo = "sad"
>>> print "%s is not %s" % (foo, goo)
happy is not sad
}}}
Using a dictionary ({{{locals()}}}):
{{{
foo = "happy"
goo = "sad"
print "%(foo)s is not %(goo)s" % locals()
}}}
Documentation for string methods?
http://docs.python.org/library/stdtypes.html#string-methods
Or, get it in Python:
{{{
>>> stringFoo = "this is a string"
>>> for thing in dir(stringFoo):
>>> print thing
capitalize
center
count
decode
encode
endswith
expandtabs
find
index
isalnum
isalpha
isdigit
islower
isspace
istitle
isupper
join
ljust
lower
lstrip
partition
replace
rfind
rindex
rjust
rpartition
rsplit
rstrip
split
splitlines
startswith
strip
swapcase
title
translate
upper
zfill
}}}
http://www.python.org/dev/peps/pep-0008/
If you have questions about the proper and acceptable ways to write you code, look there. good stuff.
Google has their own Python style guide:
http://google-styleguide.googlecode.com/svn/trunk/pyguide.html
This is all thanks to a tip from Matt Vitalone (I've modified it slightly).
If you want to get custom style sheets and icons working in your ~PySide apps, this is a pretty approachable solution.
{{{
from PySide import QtGui, QtCore
gPathToIcons = "C:/some/path/to/icon/files"
class MyAwesomePySideWindow(QtGui.QWidget)
def __init__(self, parent=None, customStyleSheet="c:/path/to/someAwesome.stylesheet"):
# This must be done, or Unreal Editor will lock up during QWidget instancing.
# Not sure why, that's just the way it is. But we need to do it anyway to get
# the app instance so we can set the style sheet.
app = None
if not QtGui.QApplication.instance():
app = QtGui.QApplication(sys.argv)
else:
app = QtGui.QApplication.instance()
if customStyleSheet is not None:
# Update the path to where PySide will search for icons:
QtCore.QDir.setSearchPaths("icons", [gPathToIcons])
# Load the style sheet:
openedSheet = str(open(customStyleSheet, "r").read())
app.setStyle('WindowsVista') # Because reasons
app.setStyleSheet(openedSheet)
super(Window, self).__init__(parent)
# Any other init code goes below here...
}}}
https://www.w3schools.com/cssref/
----
Also see:
* [[PySide : Changing background color]]
Per this blog:
https://www.mrdbourke.com/how-i-got-tensorflow-developer-certified/
* Certification web site: https://www.tensorflow.org/certificate
** The handbook (what is expected) : https://www.tensorflow.org/extras/cert/TF_Certificate_Candidate_Handbook.pdf
Courses:
* https://www.coursera.org/professional-certificates/tensorflow-in-practice
* https://www.amazon.com/Hands-Machine-Learning-Scikit-Learn-TensorFlow/dp/1492032646
* http://introtodeeplearning.com/
* https://www.jetbrains.com/pycharm/learning-center/
Extras:
* https://www.youtube.com/channel/UCcIXc5mJsHVYTZR1maL5l9w/playlists
* https://www.tensorflow.org/api_docs/python/tf
* https://www.youtube.com/playlist?list=PLQY2H8rRoyvwLbzbnKJ59NkZvQAW9wLbx
Found a couple different solutions online. One had already been converted to Python, and I converted the other. I wanted to see which was faster, so I did a simple unit test that can be performed. My result are shown at the bottom, but it looks like {{{pntInPoly()}}} is about 20% faster than {{{point_inside_polygon()}}}.
{{{
# 2dPointInPoly.py
def point_inside_polygon(point, poly):
"""
Copied from here: http://www.ariel.com.au/a/python-point-int-poly.html
Which was adapted from the c code here: http://paulbourke.net/geometry/insidepoly/
point : (x,y) point to test
poly : list of (x,y) vertex positions
return : True/False
"""
x,y = point
n = len(poly)
inside = False
p1x,p1y = poly[0]
for i in range(n+1):
p2x,p2y = poly[i % n]
if y > min(p1y,p2y):
if y <= max(p1y,p2y):
if x <= max(p1x,p2x):
if p1y != p2y:
xinters = (y-p1y)*(p2x-p1x)/(p2y-p1y)+p1x
if p1x == p2x or x <= xinters:
inside = not inside
p1x,p1y = p2x,p2y
return inside
def pntInPoly(point, verts):
"""
Adapted from c code here:
http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
point : (x,y) point to test
verts : list of (x,y) vertex positions
return : True/False
"""
c = False
vertx = [xy[0] for xy in verts]
verty = [xy[1] for xy in verts]
j = len(verts) -1
for i in range(len(verts)):
if (verty[i] > point[1]) != (verty[j]>point[1]) and \
(point[0] < (vertx[j]-vertx[i]) * (point[1]-verty[i]) / (verty[j]-verty[i]) + vertx[i]):
c = not(c)
j = i
return c
if __name__ == "__main__":
"""
Test!
"""
pointA = (.5, .5) # middle of both
pointB = (-2, 0) # outside of both
pointC = (.2, .8) # inside square, outside diamond
square = ((0,0), (0,1), (1,1), (1,0))
diamond = ((0,.5), (.5,1), (1,.5), (.5,0))
print "--------------------"
print "pointA (middle of both):", pointA
print "pointB (outside of both):", pointB
print "pointC (inside square, outside diamond):", pointC
print "square:", square
print "diamond:", diamond
print "--------------------"
print "point_inside_polygon:"
print "A in square:", point_inside_polygon(pointA, square)
print "B in square:", point_inside_polygon(pointB, square)
print "C in square:", point_inside_polygon(pointC, square)
print "A in diamond:", point_inside_polygon(pointA, diamond)
print "B in diamond:", point_inside_polygon(pointB, diamond)
print "C in diamond:", point_inside_polygon(pointC, diamond)
print "--------------------"
print "pntInPoly:"
print "A in square:", pntInPoly(pointA, square)
print "B in square:", pntInPoly(pointB, square)
print "C in square:", pntInPoly(pointC, square)
print "A in diamond:", pntInPoly(pointA, diamond)
print "B in diamond:", pntInPoly(pointB, diamond)
print "C in diamond:", pntInPoly(pointC, diamond)
print "--------------------"
import time
start = time.time()
for i in range(1000):
point_inside_polygon(pointA, square)
end = time.time()
total = end - start
print ("Completed 1000 iterations of point_inside_polygon() in %.3f seconds, %.5f sec. per test."+
"")%(total, total/1000.0)
start = time.time()
for i in range(1000):
pntInPoly(pointA, square)
end = time.time()
total = end - start
print ("Completed 1000 iterations of pntInPoly() in %.3f seconds, %.5f sec. per test."+
"")%(total, total/1000.0)
}}}
My results:
(Macbook Air - 2.13 ~GHz Intel Core 2 Duo, 4 gb ram)
{{{
--------------------
pointA (middle of both): (0.5, 0.5)
pointB (outside of both): (-2, 0)
pointC (inside square, outside diamond): (0.2, 0.8)
square: ((0, 0), (0, 1), (1, 1), (1, 0))
diamond: ((0, 0.5), (0.5, 1), (1, 0.5), (0.5, 0))
--------------------
point_inside_polygon:
A in square: True
B in square: False
C in square: True
A in diamond: True
B in diamond: False
C in diamond: False
--------------------
pntInPoly:
A in square: True
B in square: False
C in square: True
A in diamond: True
B in diamond: False
C in diamond: False
--------------------
Completed 1000 iterations of point_inside_polygon() in 0.050 seconds, 0.00005 sec. per test.
Completed 1000 iterations of pntInPoly() in 0.042 seconds, 0.00004 sec. per test.
}}}
For some reason, I keep forgetting the specifics. So let's make a note:
Presume you have a list of numbers, and you want to make sure all the numbers are within some very small tolerance. Any number outside that tolerance would be considered a fail:
{{{
tol = .000001
def check(val):
if val > -tol and val < tol:
return False
else:
return True
vals = (0.0, 0, 1.2722218725854067e-14)
if filter(check, vals):
print "failed"
else:
print "passed"
# passed
}}}
In this case, all the numbers pass.
Something like this would fail:
{{{
vals = (0.0, .1, 1.2722218725854067e-14)
}}}
----
Optionally, you can write this as a {{{lambda}}} to get rid of the {{{check}}} function and make it even shorter:
{{{
vals = (0.0, 0.0, 1.2722218725854067e-14)
tol = .000001
if filter(lambda x: x < -tol or x > tol, vals):
print "failed"
else:
print "passed"
}}}
Simple timer tool implemented as a [[context manager|with statement]].
{{{
timer.py
import time
class Timer(object):
def __init__(self, d="Default"):
"""
Parameters:
d : string : Default 'Default' : A 'description' to apply to the timer
when it prints. If multiple timers are being called to, this will
help distinguish them.
"""
self.description = d
def __enter__(self):
self.time = time.time()
def __exit__(self, exc_type, exc_value, traceback):
finalTime = time.time() - self.time
print "#-- %s timer : ran for %.3f seconds --#"%(self.description, finalTime)
# Returning True will hide any exceptions that were raised, returning
# False will re-raise them.
return False
}}}
And use it:
{{{
from timer import Timer
# Wrap your code with the timer:
with Timer("Awesome"):
myAwesomeFunction()
#-- Awesome timer : ran for 2.004 seconds --#
}}}
----
Also see:
*[[How can I write a program timer?]]
Python docs:
*http://docs.python.org/library/tkinter.html#module-Tkinter : Main docs
*http://docs.python.org/library/tix.html#module-Tix : Tix is a Tkinter extension
*http://docs.python.org/library/turtle.html#module-turtle : Turtle graphics in Tkinter
----
Other web:
*[[Tk in Wikipedia|http://en.wikipedia.org/wiki/Tk_%28computing%29]]
*http://effbot.org/tkinterbook/
*http://wiki.python.org/moin/TkInter
*http://www.pythonware.com/library/tkinter/introduction/
*http://infohost.nmt.edu/tcc/help/pubs/tkinter/ (recommended)
*http://tkinter.unpythonic.net/wiki/
/***
Contains the stuff you need to use Tiddlyspot
Note you must also have UploadPlugin installed
***/
//{{{
// edit this if you are migrating sites or retrofitting an existing TW
config.tiddlyspotSiteId = 'pythonwiki';
// make it so you can by default see edit controls via http
config.options.chkHttpReadOnly = false;
window.readOnly = false; // make sure of it (for tw 2.2)
window.showBackstage = true; // show backstage too
// disable autosave in d3
if (window.location.protocol != "file:")
config.options.chkGTDLazyAutoSave = false;
// tweak shadow tiddlers to add upload button, password entry box etc
with (config.shadowTiddlers) {
SiteUrl = 'http://'+config.tiddlyspotSiteId+'.tiddlyspot.com';
SideBarOptions = SideBarOptions.replace(/(<<saveChanges>>)/,"$1<<tiddler TspotSidebar>>");
OptionsPanel = OptionsPanel.replace(/^/,"<<tiddler TspotOptions>>");
DefaultTiddlers = DefaultTiddlers.replace(/^/,"[[WelcomeToTiddlyspot]] ");
MainMenu = MainMenu.replace(/^/,"[[WelcomeToTiddlyspot]] ");
}
// create some shadow tiddler content
merge(config.shadowTiddlers,{
'WelcomeToTiddlyspot':[
"This document is a ~TiddlyWiki from tiddlyspot.com. A ~TiddlyWiki is an electronic notebook that is great for managing todo lists, personal information, and all sorts of things.",
"",
"@@font-weight:bold;font-size:1.3em;color:#444; //What now?// @@ Before you can save any changes, you need to enter your password in the form below. Then configure privacy and other site settings at your [[control panel|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/controlpanel]] (your control panel username is //" + config.tiddlyspotSiteId + "//).",
"<<tiddler TspotControls>>",
"See also GettingStarted.",
"",
"@@font-weight:bold;font-size:1.3em;color:#444; //Working online// @@ You can edit this ~TiddlyWiki right now, and save your changes using the \"save to web\" button in the column on the right.",
"",
"@@font-weight:bold;font-size:1.3em;color:#444; //Working offline// @@ A fully functioning copy of this ~TiddlyWiki can be saved onto your hard drive or USB stick. You can make changes and save them locally without being connected to the Internet. When you're ready to sync up again, just click \"upload\" and your ~TiddlyWiki will be saved back to tiddlyspot.com.",
"",
"@@font-weight:bold;font-size:1.3em;color:#444; //Help!// @@ Find out more about ~TiddlyWiki at [[TiddlyWiki.com|http://tiddlywiki.com]]. Also visit [[TiddlyWiki.org|http://tiddlywiki.org]] for documentation on learning and using ~TiddlyWiki. New users are especially welcome on the [[TiddlyWiki mailing list|http://groups.google.com/group/TiddlyWiki]], which is an excellent place to ask questions and get help. If you have a tiddlyspot related problem email [[tiddlyspot support|mailto:support@tiddlyspot.com]].",
"",
"@@font-weight:bold;font-size:1.3em;color:#444; //Enjoy :)// @@ We hope you like using your tiddlyspot.com site. Please email [[feedback@tiddlyspot.com|mailto:feedback@tiddlyspot.com]] with any comments or suggestions."
].join("\n"),
'TspotControls':[
"| tiddlyspot password:|<<option pasUploadPassword>>|",
"| site management:|<<upload http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/store.cgi index.html . . " + config.tiddlyspotSiteId + ">>//(requires tiddlyspot password)//<br>[[control panel|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/controlpanel]], [[download (go offline)|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/download]]|",
"| links:|[[tiddlyspot.com|http://tiddlyspot.com/]], [[FAQs|http://faq.tiddlyspot.com/]], [[blog|http://tiddlyspot.blogspot.com/]], email [[support|mailto:support@tiddlyspot.com]] & [[feedback|mailto:feedback@tiddlyspot.com]], [[donate|http://tiddlyspot.com/?page=donate]]|"
].join("\n"),
'TspotSidebar':[
"<<upload http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/store.cgi index.html . . " + config.tiddlyspotSiteId + ">><html><a href='http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/download' class='button'>download</a></html>"
].join("\n"),
'TspotOptions':[
"tiddlyspot password:",
"<<option pasUploadPassword>>",
""
].join("\n")
});
//}}}
See [[Sequence Types|http://www.python.org/doc/current/lib/typesseq.html]]
A tuple is an arbitrary collection of values which can be treated as a unit. In many ways a tuple is like a list, but with the significant difference that tuples are immutable which is to say that you can’t change them nor append to them once created. Tuples are represented by parentheses containing a comma separated list of values:
{{{
>>> key = (lastname, firstname)
>>> point = x, y, z # parenthesis optional
>>> x, y, z = point
>>> singleton = (1,) # trailing comma!
>>> empty = () # parentheses!
}}}
tuples vs. lists: tuples, like strings, are immutable (Can't be changed in-place)
In Python 3.7 the [[typing|https://docs.python.org/3/library/typing.html]] module was provided to aid with type hints. See those docs for more details on its syntax and usage.
Also see:
https://mypy.readthedocs.io/en/stable/cheat_sheet_py3.html
Since I use Wingware as my IDE, it supports the {{{typing}}} module as well.
https://wingware.com/doc/edit/analysis-helping-type-hints
It also supports the hint styles standardized by [[PEP 484|https://www.python.org/dev/peps/pep-0484/]] (Python 3.5+) and [[PEP 526|https://www.python.org/dev/peps/pep-0526/]] (Python 3.6+) is another way to help Wing understand difficult-to-analyze code.
NOTE : for doing any type of 'advanced' type hinting in Python 3.7+, like subscripting a type : ({{{spam: list[float]}}}) : You'll need the below import at the top of your module:
{{{
from __future__ import annotations
}}}
For example, let's say you're interating over a list of custom class instances. You can tell what Wing what those types are via the {{{type: Isthis}}} comment:
{{{
for inst in myCustomClassInstances: # type: CustomClass
inst.someMethod() # wing will now auto-complete the methods as you type.
}}}
You can also add argument hints via '{{{functionOrMethod(parameter: ArgumentType)}}}', and return hints via '{{{def functionOrMethod() -> ReturnType:}}}':
{{{
import random
class Eggs:
def someMethod(self) -> float: # tell what this method returns
return 3.0
def someOtherMethod(self) -> (float, int) # Can pass in a tuple of types if this returns as sequence, but this is an FYI to the reader only: Wing can't use this info.
return return random.choice([3.3, 5, 3.2, 75])
def spam(eggs: Eggs) -> float: # Tell it both the argument type (Eggs), and the return type (float)
return eggs.someMethod() # Wing will now auto-complete the methods for the Eggs class as you type them.
}}}
What if you want to return a 'list' of 'things'? Or a list of things that could be different things?
{{{
def foo(spam: list[(str, float)] )-> list[str]:
return [str(item) for item in spam]
}}}
You can also provide a string for the 'thing' being returned. This really only helps humans reading it, but if you have a function that returns an instance that wasn't imported into the module, you can use this to still hint people:
{{{
def spam() -> "CustomClass":
pass
def eggs() -> list["CustomClass"]:
pass
}}}
----
Some issues
If working on a class, and you try to return an instance of your class, hinting will fail, since that class hasn't yet been defined. There are two solutions per this link:
https://stackoverflow.com/questions/33533148/how-do-i-type-hint-a-method-with-the-type-of-the-enclosing-class
A - Use {{{from __future__ import annotations}}} : This works in Python 3.7 +
{{{
from __future__ import annotations
class Spam:
@classmethod
def eggs(cls) -> Spam:
return cls
}}}
B - If < Python 3.7: : Wrap your hints in strings. Works, but feels gross
{{{
class Spam:
@classmethod
def eggs(cls) -> 'Spam':
return cls
}}}
Often times I'll want to type-check an object to make sure its what I'm expecting. In the past I'd do something like this:
{{{
myVar = []
if type(myVar) is type([]):
# If myVar is the same type as a list, do something...
print type(myVar)
# myVar is a list!
}}}
This always seemed a bit clunky though, comparing an object to a new one built at the time of comparison.
This also breaks down if your object is a sublcass of what you're trying to compare against:
{{{
import types
class MyList(types.ListType):
pass
foo = MyList()
foo.append("index0")
print foo
if type(foo) is type([]):
print "foo is a list!"
else:
print "foo is not a list..."
# ['index0']
# foo is not a list...
}}}
The {{{isinstance}}} built-in function combined with the {{{types}}} module handles this much better:
{{{
import types
class MyList(types.ListType):
pass
foo = MyList()
if isinstance(foo, types.ListType):
print "foo is a list!"
# foo is a list!
}}}
You can also test against multiple types at once:
{{{
var = [1,2,3]
print isinstance(var, (list, tuple))
True
}}}
----
Also see:
*[[string type comparisons]]
There's more than one program you can use to make UI's with Python, but Tkinter ships with it, and appears to be the most common.
How to pronounce? Good question. I've been searching and it seems to be all over the place:
*Tee-kinter
*Tink-ter
*~Tee-Kay-inter - I'm leaning towards this one, since this is the '~Tk-Interface'
''Concepts:''
*You create UI elements by instancing objects from the classes of the Tkinter module.
*There can only be one root window in a Tkinter program.
*//Widgets// are customizable classes ({{{Button}}}, {{{Frame}}}, etc).
*//Options// are 'keyword arguments': {{{text="spam"}}}
*//Compositions// refer to object embedding, not pathnames: {{{Label(Top,...)}}}
*UI's are 'event driven' programs.
*'event': Things that happen when accessing the program's objects. For example, 'pressing a button' could be an event.
*'event handler': Code that runs when an event occurs. For example, the code that executes when the button is pressed.
*You 'bind' (or, associate) //events// to //event handlers//.
*The program runs in an 'event loop', where it waits for the event's you've authored to occur.
*When you execute a UI, it will also open an accompanying console window. If you //don't// want this to happen, (on Windows) rename the extension from {{{.py}}} to {{{.pyw}}}
*When making a widget, you //don't// have to assign it to a variable name: You only need to if you later need to access the data.
*Widgets are positioned with one of the three //geometry managers//: {{{Place}}}, {{{Pack}}}, or {{{Grid}}}. These managers can be called with methods {{{place}}}, {{{pack}}}, {{{grid}}}, available in every Widget.
''UI Tree''
*root window
**frame (a widget, that can hold other widgets)
*** widgets (labels, buttons, etc)
''Example UI #1'' (very simple)':
{{{
# import all the functions from Tkinter into the default
# namespace. This is ok, it's designed to do that:
from Tkinter import *
# create root window
root = Tk()
root.title("My Window")
root.geometry("200x85")
# create a frame in the window to hold other widgets
frm = Frame(root)
# grid is a method all widgets have, which is associated
# with a layout manager. Accessing a .grid method
# makes the widget visible
frm.grid()
# create a button in the frame
bttn1 = Button(frm, text = "Button1")
bttn1.grid()
# create a second button in the frame, using
# the .configure method of Button, which lets
# you modify it after the fact:
bttn2 = Button(frm)
bttn2.grid()
bttn2.configure(text = "Button2")
# create a third button in the frame using
# Buttons "text" option, which acts like
# a dictionary:
bttn3 = Button(frm)
bttn3.grid()
bttn3["text"] = "Button3"
# kick off the window's event loop
root.mainloop()
}}}
''Example UI #2'' (Class based)
I pulled and modified this example from 'Python Programming for the absolute beginner". It makes a window that has a field to enter some text, and when you press the button, it fills the lower text box with that text.
{{{
# Many places say it's just fine to 'import *', but I'm sucker for namespaces:
import Tkinter as tk
class App(tk.Tk):
"""
This class is a subclass of the Tk object.
"""
def __init__(self):
"""
Create the window, dispaly its contents, start the event loop.
"""
tk.Tk.__init__(self)
self.title("TkWin 02")
self.geometry("250x150")
self.populate()
self.mainloop()
def populate(self):
"""
The guts of the window go in here:
"""
self.frame = tk.Frame(self)
self.frame.grid()
self.label = tk.Label(self.frame, text="This is a top label that spans multiple columns")
self.label.grid(row=0, column=0, columnspan=2, sticky=tk.W)
self.someText = tk.Label(self.frame, text="Enter something:")
self.someText.grid(row=1, column=0, sticky=tk.W)
self.entry = tk.Entry(self.frame)
self.entry.grid(row=1, column=1, sticky=tk.W)
self.b1 = tk.Button(self.frame, text="Press!", command=self.update_text)
self.b1.grid(row=2, column=0, sticky=tk.W)
self.textBox = tk.Text(self.frame, width=35, height=5, wrap=tk.WORD)
self.textBox.grid(row=3, column=0, columnspan=2, sticky=tk.W)
def update_text(self):
text = self.entry.get()
self.textBox.insert(0.0, text)
if __name__ == "__main__":
App()
}}}
Tk widgets have a {{{grid()}}} method (in addition to {{{place}}} and {{{pack}}} methods), based on the {{{Grid}}} //geometry manager//. This helps display the widget in the {{{Frame}}}. Common values include:
*{{{row}}} : which row the widget lives in (0 based index)
*{{{column}}} : which column the widget lives in (0 based index)
*{{{columnspan}}} : how many columns the widget spans
*{{{sticky}}} : How to justify a widget in a cel (N, S, E, W. These stand for North, South, East, & West)
*...more...
Example:
{{{
but = Button(someFrame, row = 0, column = 0, columnspan = 2, sticky = W)
}}}
Questions:
*Are grids 3x3 by default?
Also see:
*[[UI basics with Tkinter]]
*[[Program]] : Are the //concepts// behind implementing a idea. They are usually made up of one or more Modules
*[[module]] (a file saved on disk, usually with a {{{.py}}} extension)
**[[Statement]]
**[[Function]] (executed)
**[[Function]] (defined)
***[[argument]]
***[[return]]
***[[Statement]]
***[[Function]] (executed)
***[[Function]] (defined. Yup, you can have functions nested in functions)
**[[Class]] (also see [[Class - advanced]])
***[[Method]] (defined. Methods //are// functions. But when defined in a Class, the become 'methods')
***[[Function]] (executed)
Since as of this authoring I'm an xml noob, overview:
----
Some xml terminology links:
http://cnx.org/eip-help/terminology
http://www.xmlnews.org/docs/xml-basics.html
----
Some Python docs on dom.minidom {{{Document}}} objects:
http://docs.python.org/library/xml.dom.html#document-objects
----
''Tags, Attributes, & Elements'':
>"XML __tags__ begin with the less-than character (“{{{<}}}”) and end with the greater-than character (“{{{>}}}”). You use tags to mark the start and end of __elements__, which are the logical units of information in an XML document."
>"An __element__ consists of a start __tag__, possibly followed by text and other complete elements, followed by an end __tag__."
{{{tags}}} in action:
{{{
<tagA>
<tagB> text </tagB>
</tagA>
}}}
Above, {{{tagA}}} in its completeness is an //element//. {{{tagB}}} is also an //element//.
Introducing __{{{attribute}}}__ names, and values:
{{{
<tagA>
<tagB attrName="attrValue"> text </tagB>
</tagA>
}}}
Attribute names are never in quotes, while attribute values are //always// in quotes. Also, attributes and elements are //case sensitive//.
Tags and text can be intermixed (but tags //can't// be overlapped with other tags):
{{{
<tagA>
some text <tagB> tagB text </tagB>
<tagC> <tagD> stuff </tagD> </tagC> text text text
</tagA>
}}}
The above could be viewed as such:
*(tagA)
**some text
**(tagB)
***text
**(tagC)
***(tagD)
****stuff
**text text text
There can only ever be one root element. The next example is invalid:
{{{
<tagA> text </tagA>
<tagB> text </tagB>
}}}
This would fix it:
{{{
<root>
<tagA> text </tagA>
<tagB> text </tagB>
</root>
}}}
----
''Comments'':
Surrounding text with {{{<!-- -->}}} will cause the xml to igore the markup:
{{{
<!-- This is a comment that will be ignored -->
}}}
----
''Declaration'':
Xml files can optionally start with a declaration:
{{{
<?xml version="1.0"?>
}}}
----
Pulled from:
http://www.flightlab.com/~joe/sgml/faq-not.txt
----
{{{
Q. I've tried reading the (XML | SGML | XSL | XPATH | DSSSL | ...)
specification, but it doesn't make any sense! There's too
much jargon!
A. Specification authors deliberately obfuscate the text of
ISO and W3C standards to ensure that normal people
(e.g., Perl programmers) can't use the technology without
assistance from the so-called "experts" who designed the
specs.
Fortunately, there is a handy translation table you can use:
--------------------------------------------------
ISO/W3C terminology Common name
--------------------------------------------------
attribute tag
attribute value tag
attribute value literal tag
attribute value specification tag
character reference tag
comment tag
comment declaration tag
declaration tag
document type declaration tag
document type definition tag
element tag
element type tag
element type name tag
entity tag
entity reference tag
general entity tag
generic identifier tag
literal tag
numeric character reference tag
parameter entity tag
parameter literal tag
processing instruction tag
tag command
--------------------------------------------------
With the help of this table, even Visual Basic programmers
should have no trouble deciphering ISO prose.
}}}
According to the [[Python Docs|http://docs.python.org/lib/specialattrs.html]], {{{__dict__}}} is:
*"A dictionary or other mapping object used to store an object's (writable) attributes."
I believe this could also be considered a 'symbol table'.
But how is it used, and what for?
Like expressed above, {{{__dict__}}} holds information (attributes) on a given //object//. It is a dictionary of //all// the available data the object exposes to the user. Simple example:
{{{
class MyObject(object):
def __init__(self):
self.first = 1
self.second = 2
third = 42
larry = MyObject()
print larry.__dict__
# {'second': 2, 'first': 1}
larry.goof = 52
print larry.__dict__
# {'goof': 52, 'second': 2, 'first': 1}
}}}
We create an object called {{{MyObject}}}. We give it two attributes, {{{.first}}} and {{{.second}}} and one //local variable// {{{third}}} (see notes on [[variable scope|Python variable scope]]). After we instance {{{MyObject}}} as {{{larry}}}, we print {{{larry}}}'s {{{__dict__}}}, exposing the inside of our object, to the attributes it contains. We then create a //new// attribute {{{.goof}}}, and then reprint {{{__dict__}}} proving it exists.
----
Also see:
*[[Special Attributes]]
*[[How can I query the variable names of a defined scope?]] ( {{{vars()}}} )
{{{__repr__}}} & {{{__str__}}} are special methods that objects possess.
I have read in some cases {{{__repr__}}} is the result given from a function that has "full precision", to be 'passed on' to other functions', while {{{__str__}}} is designed to be more human-readable.
But, this isn't what the [[official docs say|http://docs.python.org/reference/datamodel.html#object.__repr__]] for {{{__repr__}}}:
<<<
"Called by the {{{repr()}}} built-in function and by string conversions (reverse quotes) to compute the “official” string representation of an object. If at all possible, ''this should look like a valid Python expression that could be used to recreate an object with the same value'' (given an appropriate environment). If this is not possible, a string of the form {{{<...some useful description...>}}} should be returned. The return value must be a string object. If a class defines {{{__repr__()}}} but not {{{__str__()}}}, then {{{__repr__()}}} is also used when an “informal” string representation of instances of that class is required."
<<<
So to me, {{{__repr__}}} really means 'representation', and I've heard it called the 'reproduction string'.
And, [[official docs|http://docs.python.org/reference/datamodel.html#object.__str__]] for {{{__str__}}}:
<<<
"Called by the {{{str()}}} built-in function and by the {{{print}}} statement to compute the “informal” string representation of an object. This differs from {{{__repr__()}}} in that it does not have to be a valid Python expression: a more convenient or concise representation may be used instead. The return value must be a string object."
<<<
What does that actually mean? Example:
{{{
class Spam(object):
def __init__(self, val):
self.val = val
def __repr__(self):
return "<Spam(%s)>"%self.val
def __str__(self):
return str(self.val)
eggs = Spam(4)
print repr(eggs)
print eggs.__repr__()
print `eggs`
print eggs
}}}
{{{
<Spam(4)>
<Spam(4)>
<Spam(4)>
4
}}}
{{{repr}}} can also be called to via back-tick: {{{`}}} around the variable.
----
Also see:
*[[Special Methods]]
Link to Python's [[Exception Hierarchy|http://docs.python.org/2/library/exceptions.html#exception-hierarchy]]
From the docs http://docs.python.org/library/exceptions.html:
>Exceptions should be class objects. The exceptions are defined in the module {{{exceptions}}}.
Python "Tutorial" on Exceptions [[here|http://docs.python.org/tut/node10.html]].
''User defined exception'' docs: http://docs.python.org/tutorial/errors.html#user-defined-exceptions
In a nutshell, an exception is a way to catch an error, and do something with that knowledge.
Python docs on the {{{try}}} statement [[here|http://docs.python.org/reference/compound_stmts.html#the-try-statement]]
I read this in some [[Python docs|http://docs.python.org/howto/doanddont.html#exceptions]], and I think it's a pretty good thing to go by:
>Exceptions are a useful feature of Python. You should learn to raise them whenever something unexpected occurs, and catch them only where you can do something about them.
{{{
try:
python code
except:
do something else
}}}
The base {{{except}}} will handle ALL different kinds of exceptions. It can get a lot more detailed, and you can raise an exception on very specific things. Here's another example, from the tutorial:
{{{
while True:
try:
x = int(raw_input("Please enter a number: "))
break
except ValueError:
print "Oops! That was no valid number. Try again..."
}}}
As you can see, in this case the exception will only happen if it's a "~ValueError".
You can also use {{{raise(<someException(<someDescription>)>)}}} in your code:
{{{
if(True):
raise(Exception("This is true, and I'm tossing an exception"))
}}}
The except clause can also take a variable after the exception name. See the 'Tutorial' link above for more on this:
{{{
try:
# something...
except Exception, inst:
print inst
}}}
----
You can make your own exception types very easily. Here is about as simple as it can get (from [[here|http://www.dummies.com/how-to/content/how-to-create-and-use-custom-exceptions-in-python.html]]).
{{{
class MyException(Exception):
def __init__(self, arg):
self.strerror = arg
self.args = {arg}
}}}
And to detect for it:
{{{
try:
raise MyException("Fail, so fail.")
except MyException, e:
print "Caught MyException:", e
# Caught MyException: Fail, so fail.
}}}
----
Also see:
*[[How do I catch \ handle exceptions?]]
{{{
filter(function or None, sequence) -> list, tuple, or string
}}}
Returns those items in the provided sequence that are true based on the passed in function. If no function is given (None), then the data type is compared against true|false testing.
{{{
# return the numbers divisible by three:
foo = [2, 18, 9, 22, 17, 24, 8, 12, 27]
print filter(lambda x: x % 3 ! 0, foo)
[18, 9, 24, 12, 27]
}}}
So, if our lambda function returns back something cleanly divisible by zero, the filter is true, so the current item in foo we're checking is added to our list of things to return.
Docs:
*http://docs.python.org/reference/expressions.html#yieldexpr
*http://docs.python.org/reference/simple_stmts.html#yield
Generators are created by adding 'yield' to a function loop:
The function itself looks something like this:
{{{
def gen(things):
for thing in things:
# ...do stuff with things...
yield newThing
}}}
or:
{{{
def gen(someArgs):
while someCondition:
# ...do stuff with things...
yield someItem
}}}
Generators have a default .next method you can call to advance in the loop and 'yield' (return) the next item:
{{{
stuff = [my, list, of, stuff]
g = gen(stuff)
g.next()
}}}
When the generator runs past the last item to iterate on, it raises a {{{StopIteration}}} exception.
----
For example, make a generator that returns the square of a number, counting up from {{{1}}}, each time you call to it.
{{{
def squares(start=1):
i=start
while True:
number = i
square = i**2
i += 1
yield square, number
}}}
{{{
squared = squares()
print squared.next()
print squared.next()
print squared.next()
}}}
{{{
(1, 1)
(4, 2)
(9, 3)
}}}
Generator objects are also iterators which you can loop over:
{{{
squared = squares()
num = 0
sq = []
for item in squared: # this will run forever...
sq.append(item[0])
num += 1
if num >= 10:
break # So we need a way to stop it:
print sq
}}}
{{{
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
}}}
Or:
{{{
squared = squares()
sq = []
for i in range(10):
sq.append(squared.next()[0])
print sq
}}}
{{{
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
}}}
Referenced I pulled from is [[here|http://www.secnetix.de/~olli/Python/lambda_functions.hawk]]
{{{
lambda arg(s): 'code arg(s)'
}}}
Why use lambda's? The next part makes a bit of sense:
>Lambda's are [[expressions|Statement]] that generate a new [[Function]] to be called later (//similar// to a function definition statement (def), but different). Since they are [[expressions|Statement]], they can be used in places that [[Function]] definitions can not, such as within list and dictionaries.
{{{
double = lambda x: 2*x
double(4)
8
}}}
So as you can see, 'lambda' is the name of your virtual function, the next character is one or more [[argument]]s to be passed in, and after the colon ':' comes the bulk of the function.
{{{
# our lambda:
lFunc = lambda x, y: x*y
print lFunc(2,5)
# 10
# do it with a function def:
def dFunc(x,y):
return x*y
print dFunc(2,5)
# 10
}}}
From above, in the lambda we assign the anonymous function to variable {{{lFunc}}}, then call to {{lFfunc}}} with arguments.
In the def, we create a //function objec//t called {{{dFunc}}}, then call to {{{dFunc}}} with arguments.
----
Other Examples:
{{{
sentence = 'It is raining cats and dogs'
words = sentence.split()
print words
['It', 'is', 'raining', 'cats', 'and', 'dogs']
# this uses lambda in map:
lengths = map(lambda word: len(word), words)
print lengths
[2, 2, 7, 4, 3, 4]
}}}
----
To expand on my reason behind using Lambda's above, here is an example that creates a list of functions (thanks to lambda) that will raise the passed in arg to the power of the index of the list. Each index of the list is its own function:
{{{
def makeFuncs():
ret = []
for i in range(4):
ret.append(lambda x, i=i: i ** x)
return ret
funcs = makeFuncs()
print funcs[0](2)
# 0
print funcs[1](2)
# 1
print funcs[2](2)
# 4
print funcs[3](2)
# 9
print funcs[4](2)
# 16
}}}
The key to this working is the '{{{, i=i: }}}' part: If it was just '{{{i}}}', every Lambda would have the same {{{i}}} value when {{{makeFuncs()}}} loop was complete, since they'd all be pointing to the //same// {{{i}}} object. But by setting up a [[default argument|Default Arguments]], it makes sure that each loop has its own unique value.
----
Lambda's can also be used in callbacks in Tkinter widgets: When authoring callbacks for things like buttons, you can author a lambda as the command, rather than having an external function being called too:
{{{
import sys
# insert window code...
bttn1 = Button(text = "U press now", command=(lambda:sys.stdout.write('Spam\n')))
}}}
{{{
map(function, sequence[, sequence, ...]) -> list
}}}
Map runs a function on a list, and returns back a new list. I am told this is faster than a loop.
{{{
numbers = [1, 2, 3, 4]
def adder(x):
return x + x
map(adder, numbers)
[2, 4, 6, 8]
}}}
Map can also take more than one sequence arugment.
{{{
letters = ["a", "b", "c", "d"]
nums = ["1", "2", "3", "4"]
def addtwo(x, y):
return x+y
map(addtwo, nums, letters)
['1a', '2b', '3c', '4d']
}}}
Finally, if no function argument is listed ({{{None}}}), it will combine the arguments as tuples in the result:
{{{
map(None, nums, letters)
[('1', 'a'), ('2', 'b'), ('3', 'c'), ('4', 'd')]
}}}
Here's one that will print the length of every word in a sentence.. It 'splits' the string into it's individual words, then map passes that to the lambda to find it's length, which is then added to our returned list:
{{{
print map(lambda w: len(w), 'It is raining cats and dogs'.split())
[2, 2, 7, 4, 3, 4]
}}}
Also see:
*[[How can I loop through multiple lists?]]
{{{
reduce(function, sequence[, initial]) -> value
}}}
Reduce is a tricky one. From the docs: Apply a function of two arguments cumulatively to the items of a sequence, from left to right, so as to reduce the sequence to a single value.
{{{
foo = [2, 18, 9, 22, 17, 24, 8, 12, 27]
print reduce(lambda x, y: x + y, foo)
139
}}}
This is equal to
{{{
((((((((2+18)+9)+22)+17)+24)+8)+12)+27)
}}}
Also, if the 'initial' argument is present, it is placed before the items of the sequence in the calculation, and serves as a default when the sequence is empty.
Notes taken from:
* https://docs.python.org/3/library/sys.html#sys.stdin
* https://en.wikipedia.org/wiki/Standard_streams
* https://www.askpython.com/python/python-stdin-stdout-stderr
* https://stackoverflow.com/questions/8980520/can-anyone-give-me-a-quick-tutorial-in-stdin-and-stdout-in-python-3
Overview
* {{{stdin}}} : Standard input
** {{{stdin}}} is used for all interactive input (including calls to {{{input()}}});
** This is the file-handle (file object) that a user program reads to get information from the user.
** In general, when a program is run in an interactive session, {{{stdin}}} is keyboard input.
* {{{stdout}}} : Standard output
** {{{stdout}}} is used for the output of {{{print()}}} and expression statements and for the prompts of {{{input()}}}.
** The user program writes normal information to this file-handle (file object).
** In general, when a program is run in an interactive session {{{stdout}}} is the user's {{{tty}}} (terminal/shell).
* {{{stderr}}} : Standard error
** The interpreter’s own prompts and its error messages go to {{{stderr}}}.
** The user program writes error information to this file-handle (file object). Errors are returned via the Standard error (stderr).
** This is similar to {{{sys.stdout}}} because it also prints directly to the Console. But the difference is that it only prints Exceptions and Error messages. (Which is why it is called Standard Error).
* Python provides us with file-like objects that represent {{{stdin}}}, {{{stdout}}}, and {{{stderr}}}.
** These streams are regular text files like those returned by the {{{open()}}} function.
{{{
import sys
sys.stdin
sys.stdout
sys.stderr
}}}
The [[subrprocess|https://docs.python.org/3/library/subprocess.html]] module has different ways to execute 'other' code. What are the differences between them? (As of Python 3)
Per the above docs:
<<<
The subprocess module allows you to spawn new processes, connect to their input/output/error pipes, and obtain their return codes. This module intends to replace several older modules and functions:
<<<
----
! subprocess.Popen
Wrappered by {{{run}}}, {{{Popen}}} opens a procss and keeps it live, allowing for additional communication with it.
See older notes here: [[How can I execute a system command, and capture the return?]]
! subprocess.run
{{{run}}} 'runs' the process (it's a functional wrapper around the {{{Popen}}} instance), waits until it's complete (like calling to {{{Popen().wait()}}} ) and exits, returning a {{{CompletedProcess}}} instance.
If you want to interact with the process over time, using {{{Popen}}} directly is better.
<<<
The recommended approach to invoking subprocesses is to use the run() function for all use cases it can handle. For more advanced use cases, the underlying Popen interface can be used directly.
Run the command described by args. Wait for command to complete, then return a ~CompletedProcess instance.
args is required for all calls and should be a string, or a sequence of program arguments. Providing a sequence of arguments is generally preferred, as it allows the module to take care of any required escaping and quoting of arguments (e.g. to permit spaces in file names).
<<<
Note, if providing a single string instead a list of args, you must use {{{shell=True}}} (see below).
!! To shell, or not to shell?
Passing {{{shell=True}}} literally means, "run the args in your OS's shell": The 'shell' is the 'process' being executed.
//Which// shell is used is different based on OS. For example, on Windows, this is the 'Command Prompt', {{{cmd.exe}}}.
Also:
<<<
If passing a single string, either {{{shell=True}}} or else the string must simply name the program to be executed without specifying any arguments.
If {{{shell=True}}}, the specified command will be executed through the shell. This can be useful if you are using Python primarily for the enhanced control flow it offers over most system shells and still want convenient access to other shell features such as shell pipes, filename wildcards, environment variable expansion, and expansion of ~ to a user’s home directory.
The shell argument (which defaults to False) specifies whether to use the shell as the program to execute. If {{{shell=True}}}, it is recommended to pass args as a string rather than as a sequence.
The only time you need to specify {{{shell=True}}} on ''Windows'' is when the command you wish to execute is built into the shell (e.g. dir or copy). You do *not* need {{{shell=True}}} to run a batch file or console-based executable.
<<<
Calling to an //OS shell command to do something// requires {{{shell=True}}}, or this exception will be raised: {{{builtins.FileNotFoundError: [WinError 2] The system cannot find the file specified}}}.
In this example, we're 'calling' to the Window's {{{dir}}} //shell command//, and outputting its value to a text file, based on the {{{c:\temp}}} dir. Since {{{dir}}} //is// a Windows shell command, we must pass {{{shell=True}}} so as to run those args in that interpreter.
{{{
subprocess.run(["dir", ">", "dir.txt"], cwd="c:\\temp", shell=True)
}}}
Here, we're opening a process to the Window's Explorer Application (who's exe is on the Window's PATH: Not an OS //shell command//), No need for {{{shell=True}}} here:
{{{
subprocess.run(["explorer", "/select,", "c:\\temp\\myFile.txt"])
}}}
!! Communicating with the process
<<<
The {{{input}}} argument is passed to {{{Popen.communicate()}}} and thus to the subprocess’s stdin. If used it must be a byte sequence, or a string if encoding or errors is specified or text is true. When used, the internal Popen object is automatically created with stdin=PIPE, and the stdin argument may not be used as well.
<<<
It's worth noting that since {{{run}}} "runs the process and exits", you only get once chance(?) to communicate with it via the {{{input}}} arg. If you want more communication, you'll want to work with a live {{{Popen}}} instance instead.
!! Capturing return
The return from {{{run}}} is a [[CompletedProcess|https://docs.python.org/3/library/subprocess.html#subprocess.CompletedProcess]] instance.
However, often what you want is the return from the process executed, not the return from {{{run}}} itself: To do that, you must {{{capture_output=True}}}, then intercept the {{{stdout}}} of the {{{CompletedProcess}}} instance
<<<
If capture_output is true, stdout and stderr will be captured. When used, the internal Popen object is automatically created with stdout=PIPE and stderr=PIPE. The stdout and stderr arguments may not be supplied at the same time as capture_output. If you wish to capture and combine both streams into one, use stdout=PIPE and stderr=STDOUT instead of capture_output.
<<<
{{{
completedProcess = subprocess.run(["dir"], cwd="c:\\temp", shell=True, capture_output=True)
# In Python3, stdout is bytes, so we need to decode it:
print(completedProcess.stdout.decode())
}}}
----
Also see : [[Understanding stdin, stdout, stderr]]
----
| !date | !user | !location | !storeUrl | !uploadDir | !toFilename | !backupdir | !origin |
| 18/05/2022 15:55:16 | WarpCat | [[/|http://pythonwiki.tiddlyspot.com/]] | [[store.cgi|http://pythonwiki.tiddlyspot.com/store.cgi]] | . | [[index.html | http://pythonwiki.tiddlyspot.com/index.html]] | . | ok |
| 18/05/2022 15:55:32 | WarpCat | [[/|http://pythonwiki.tiddlyspot.com/]] | [[store.cgi|http://pythonwiki.tiddlyspot.com/store.cgi]] | . | [[index.html | http://pythonwiki.tiddlyspot.com/index.html]] | . |
| 20/05/2022 13:37:08 | WarpCat | [[/|http://pythonwiki.tiddlyspot.com/]] | [[store.cgi|http://pythonwiki.tiddlyspot.com/store.cgi]] | . | [[index.html | http://pythonwiki.tiddlyspot.com/index.html]] | . |
| 20/05/2022 14:05:37 | WarpCat | [[/|http://pythonwiki.tiddlyspot.com/]] | [[store.cgi|http://pythonwiki.tiddlyspot.com/store.cgi]] | . | [[index.html | http://pythonwiki.tiddlyspot.com/index.html]] | . | ok |
| 20/05/2022 15:18:31 | WarpCat | [[/|http://pythonwiki.tiddlyspot.com/]] | [[store.cgi|http://pythonwiki.tiddlyspot.com/store.cgi]] | . | [[index.html | http://pythonwiki.tiddlyspot.com/index.html]] | . |
| 01/06/2022 09:21:42 | WarpCat | [[/|http://pythonwiki.tiddlyspot.com/]] | [[store.cgi|http://pythonwiki.tiddlyspot.com/store.cgi]] | . | [[index.html | http://pythonwiki.tiddlyspot.com/index.html]] | . |
| 25/07/2022 16:03:46 | WarpCat | [[/|http://pythonwiki.tiddlyspot.com/]] | [[store.cgi|http://pythonwiki.tiddlyspot.com/store.cgi]] | . | [[index.html | http://pythonwiki.tiddlyspot.com/index.html]] | . | ok |
| 25/07/2022 16:05:20 | WarpCat | [[/|http://pythonwiki.tiddlyspot.com/]] | [[store.cgi|http://pythonwiki.tiddlyspot.com/store.cgi]] | . | [[index.html | http://pythonwiki.tiddlyspot.com/index.html]] | . | ok |
| 25/07/2022 16:06:11 | WarpCat | [[/|http://pythonwiki.tiddlyspot.com/]] | [[store.cgi|http://pythonwiki.tiddlyspot.com/store.cgi]] | . | [[index.html | http://pythonwiki.tiddlyspot.com/index.html]] | . |
| 27/07/2022 10:36:08 | WarpCat | [[/|http://pythonwiki.tiddlyspot.com/]] | [[store.cgi|http://pythonwiki.tiddlyspot.com/store.cgi]] | . | [[index.html | http://pythonwiki.tiddlyspot.com/index.html]] | . |
/***
|''Name:''|PasswordOptionPlugin|
|''Description:''|Extends TiddlyWiki options with non encrypted password option.|
|''Version:''|1.0.2|
|''Date:''|Apr 19, 2007|
|''Source:''|http://tiddlywiki.bidix.info/#PasswordOptionPlugin|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0 (Beta 5)|
***/
//{{{
version.extensions.PasswordOptionPlugin = {
major: 1, minor: 0, revision: 2,
date: new Date("Apr 19, 2007"),
source: 'http://tiddlywiki.bidix.info/#PasswordOptionPlugin',
author: 'BidiX (BidiX (at) bidix (dot) info',
license: '[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D]]',
coreVersion: '2.2.0 (Beta 5)'
};
config.macros.option.passwordCheckboxLabel = "Save this password on this computer";
config.macros.option.passwordInputType = "password"; // password | text
setStylesheet(".pasOptionInput {width: 11em;}\n","passwordInputTypeStyle");
merge(config.macros.option.types, {
'pas': {
elementType: "input",
valueField: "value",
eventName: "onkeyup",
className: "pasOptionInput",
typeValue: config.macros.option.passwordInputType,
create: function(place,type,opt,className,desc) {
// password field
config.macros.option.genericCreate(place,'pas',opt,className,desc);
// checkbox linked with this password "save this password on this computer"
config.macros.option.genericCreate(place,'chk','chk'+opt,className,desc);
// text savePasswordCheckboxLabel
place.appendChild(document.createTextNode(config.macros.option.passwordCheckboxLabel));
},
onChange: config.macros.option.genericOnChange
}
});
merge(config.optionHandlers['chk'], {
get: function(name) {
// is there an option linked with this chk ?
var opt = name.substr(3);
if (config.options[opt])
saveOptionCookie(opt);
return config.options[name] ? "true" : "false";
}
});
merge(config.optionHandlers, {
'pas': {
get: function(name) {
if (config.options["chk"+name]) {
return encodeCookie(config.options[name].toString());
} else {
return "";
}
},
set: function(name,value) {config.options[name] = decodeCookie(value);}
}
});
// need to reload options to load passwordOptions
loadOptionsCookie();
/*
if (!config.options['pasPassword'])
config.options['pasPassword'] = '';
merge(config.optionsDesc,{
pasPassword: "Test password"
});
*/
//}}}
/***
|''Name:''|UploadPlugin|
|''Description:''|Save to web a TiddlyWiki|
|''Version:''|4.1.0|
|''Date:''|May 5, 2007|
|''Source:''|http://tiddlywiki.bidix.info/#UploadPlugin|
|''Documentation:''|http://tiddlywiki.bidix.info/#UploadPluginDoc|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0 (#3125)|
|''Requires:''|PasswordOptionPlugin|
***/
//{{{
version.extensions.UploadPlugin = {
major: 4, minor: 1, revision: 0,
date: new Date("May 5, 2007"),
source: 'http://tiddlywiki.bidix.info/#UploadPlugin',
author: 'BidiX (BidiX (at) bidix (dot) info',
coreVersion: '2.2.0 (#3125)'
};
//
// Environment
//
if (!window.bidix) window.bidix = {}; // bidix namespace
bidix.debugMode = false; // true to activate both in Plugin and UploadService
//
// Upload Macro
//
config.macros.upload = {
// default values
defaultBackupDir: '', //no backup
defaultStoreScript: "store.php",
defaultToFilename: "index.html",
defaultUploadDir: ".",
authenticateUser: true // UploadService Authenticate User
};
config.macros.upload.label = {
promptOption: "Save and Upload this TiddlyWiki with UploadOptions",
promptParamMacro: "Save and Upload this TiddlyWiki in %0",
saveLabel: "save to web",
saveToDisk: "save to disk",
uploadLabel: "upload"
};
config.macros.upload.messages = {
noStoreUrl: "No store URL in parmeters or options",
usernameOrPasswordMissing: "Username or password missing"
};
config.macros.upload.handler = function(place,macroName,params) {
if (readOnly)
return;
var label;
if (document.location.toString().substr(0,4) == "http")
label = this.label.saveLabel;
else
label = this.label.uploadLabel;
var prompt;
if (params[0]) {
prompt = this.label.promptParamMacro.toString().format([this.destFile(params[0],
(params[1] ? params[1]:bidix.basename(window.location.toString())), params[3])]);
} else {
prompt = this.label.promptOption;
}
createTiddlyButton(place, label, prompt, function() {config.macros.upload.action(params);}, null, null, this.accessKey);
};
config.macros.upload.action = function(params)
{
// for missing macro parameter set value from options
var storeUrl = params[0] ? params[0] : config.options.txtUploadStoreUrl;
var toFilename = params[1] ? params[1] : config.options.txtUploadFilename;
var backupDir = params[2] ? params[2] : config.options.txtUploadBackupDir;
var uploadDir = params[3] ? params[3] : config.options.txtUploadDir;
var username = params[4] ? params[4] : config.options.txtUploadUserName;
var password = config.options.pasUploadPassword; // for security reason no password as macro parameter
// for still missing parameter set default value
if ((!storeUrl) && (document.location.toString().substr(0,4) == "http"))
storeUrl = bidix.dirname(document.location.toString())+'/'+config.macros.upload.defaultStoreScript;
if (storeUrl.substr(0,4) != "http")
storeUrl = bidix.dirname(document.location.toString()) +'/'+ storeUrl;
if (!toFilename)
toFilename = bidix.basename(window.location.toString());
if (!toFilename)
toFilename = config.macros.upload.defaultToFilename;
if (!uploadDir)
uploadDir = config.macros.upload.defaultUploadDir;
if (!backupDir)
backupDir = config.macros.upload.defaultBackupDir;
// report error if still missing
if (!storeUrl) {
alert(config.macros.upload.messages.noStoreUrl);
clearMessage();
return false;
}
if (config.macros.upload.authenticateUser && (!username || !password)) {
alert(config.macros.upload.messages.usernameOrPasswordMissing);
clearMessage();
return false;
}
bidix.upload.uploadChanges(false,null,storeUrl, toFilename, uploadDir, backupDir, username, password);
return false;
};
config.macros.upload.destFile = function(storeUrl, toFilename, uploadDir)
{
if (!storeUrl)
return null;
var dest = bidix.dirname(storeUrl);
if (uploadDir && uploadDir != '.')
dest = dest + '/' + uploadDir;
dest = dest + '/' + toFilename;
return dest;
};
//
// uploadOptions Macro
//
config.macros.uploadOptions = {
handler: function(place,macroName,params) {
var wizard = new Wizard();
wizard.createWizard(place,this.wizardTitle);
wizard.addStep(this.step1Title,this.step1Html);
var markList = wizard.getElement("markList");
var listWrapper = document.createElement("div");
markList.parentNode.insertBefore(listWrapper,markList);
wizard.setValue("listWrapper",listWrapper);
this.refreshOptions(listWrapper,false);
var uploadCaption;
if (document.location.toString().substr(0,4) == "http")
uploadCaption = config.macros.upload.label.saveLabel;
else
uploadCaption = config.macros.upload.label.uploadLabel;
wizard.setButtons([
{caption: uploadCaption, tooltip: config.macros.upload.label.promptOption,
onClick: config.macros.upload.action},
{caption: this.cancelButton, tooltip: this.cancelButtonPrompt, onClick: this.onCancel}
]);
},
refreshOptions: function(listWrapper) {
var uploadOpts = [
"txtUploadUserName",
"pasUploadPassword",
"txtUploadStoreUrl",
"txtUploadDir",
"txtUploadFilename",
"txtUploadBackupDir",
"chkUploadLog",
"txtUploadLogMaxLine",
]
var opts = [];
for(i=0; i<uploadOpts.length; i++) {
var opt = {};
opts.push()
opt.option = "";
n = uploadOpts[i];
opt.name = n;
opt.lowlight = !config.optionsDesc[n];
opt.description = opt.lowlight ? this.unknownDescription : config.optionsDesc[n];
opts.push(opt);
}
var listview = ListView.create(listWrapper,opts,this.listViewTemplate);
for(n=0; n<opts.length; n++) {
var type = opts[n].name.substr(0,3);
var h = config.macros.option.types[type];
if (h && h.create) {
h.create(opts[n].colElements['option'],type,opts[n].name,opts[n].name,"no");
}
}
},
onCancel: function(e)
{
backstage.switchTab(null);
return false;
},
wizardTitle: "Upload with options",
step1Title: "These options are saved in cookies in your browser",
step1Html: "<input type='hidden' name='markList'></input><br>",
cancelButton: "Cancel",
cancelButtonPrompt: "Cancel prompt",
listViewTemplate: {
columns: [
{name: 'Description', field: 'description', title: "Description", type: 'WikiText'},
{name: 'Option', field: 'option', title: "Option", type: 'String'},
{name: 'Name', field: 'name', title: "Name", type: 'String'}
],
rowClasses: [
{className: 'lowlight', field: 'lowlight'}
]}
}
//
// upload functions
//
if (!bidix.upload) bidix.upload = {};
if (!bidix.upload.messages) bidix.upload.messages = {
//from saving
invalidFileError: "The original file '%0' does not appear to be a valid TiddlyWiki",
backupSaved: "Backup saved",
backupFailed: "Failed to upload backup file",
rssSaved: "RSS feed uploaded",
rssFailed: "Failed to upload RSS feed file",
emptySaved: "Empty template uploaded",
emptyFailed: "Failed to upload empty template file",
mainSaved: "Main TiddlyWiki file uploaded",
mainFailed: "Failed to upload main TiddlyWiki file. Your changes have not been saved",
//specific upload
loadOriginalHttpPostError: "Can't get original file",
aboutToSaveOnHttpPost: 'About to upload on %0 ...',
storePhpNotFound: "The store script '%0' was not found."
};
bidix.upload.uploadChanges = function(onlyIfDirty,tiddlers,storeUrl,toFilename,uploadDir,backupDir,username,password)
{
var callback = function(status,uploadParams,original,url,xhr) {
if (!status) {
displayMessage(bidix.upload.messages.loadOriginalHttpPostError);
return;
}
if (bidix.debugMode)
alert(original.substr(0,500)+"\n...");
// Locate the storeArea div's
var posDiv = locateStoreArea(original);
if((posDiv[0] == -1) || (posDiv[1] == -1)) {
alert(config.messages.invalidFileError.format([localPath]));
return;
}
bidix.upload.uploadRss(uploadParams,original,posDiv);
};
if(onlyIfDirty && !store.isDirty())
return;
clearMessage();
// save on localdisk ?
if (document.location.toString().substr(0,4) == "file") {
var path = document.location.toString();
var localPath = getLocalPath(path);
saveChanges();
}
// get original
var uploadParams = Array(storeUrl,toFilename,uploadDir,backupDir,username,password);
var originalPath = document.location.toString();
// If url is a directory : add index.html
if (originalPath.charAt(originalPath.length-1) == "/")
originalPath = originalPath + "index.html";
var dest = config.macros.upload.destFile(storeUrl,toFilename,uploadDir);
var log = new bidix.UploadLog();
log.startUpload(storeUrl, dest, uploadDir, backupDir);
displayMessage(bidix.upload.messages.aboutToSaveOnHttpPost.format([dest]));
if (bidix.debugMode)
alert("about to execute Http - GET on "+originalPath);
var r = doHttp("GET",originalPath,null,null,null,null,callback,uploadParams,null);
if (typeof r == "string")
displayMessage(r);
return r;
};
bidix.upload.uploadRss = function(uploadParams,original,posDiv)
{
var callback = function(status,params,responseText,url,xhr) {
if(status) {
var destfile = responseText.substring(responseText.indexOf("destfile:")+9,responseText.indexOf("\n", responseText.indexOf("destfile:")));
displayMessage(bidix.upload.messages.rssSaved,bidix.dirname(url)+'/'+destfile);
bidix.upload.uploadMain(params[0],params[1],params[2]);
} else {
displayMessage(bidix.upload.messages.rssFailed);
}
};
// do uploadRss
if(config.options.chkGenerateAnRssFeed) {
var rssPath = uploadParams[1].substr(0,uploadParams[1].lastIndexOf(".")) + ".xml";
var rssUploadParams = Array(uploadParams[0],rssPath,uploadParams[2],'',uploadParams[4],uploadParams[5]);
bidix.upload.httpUpload(rssUploadParams,convertUnicodeToUTF8(generateRss()),callback,Array(uploadParams,original,posDiv));
} else {
bidix.upload.uploadMain(uploadParams,original,posDiv);
}
};
bidix.upload.uploadMain = function(uploadParams,original,posDiv)
{
var callback = function(status,params,responseText,url,xhr) {
var log = new bidix.UploadLog();
if(status) {
// if backupDir specified
if ((params[3]) && (responseText.indexOf("backupfile:") > -1)) {
var backupfile = responseText.substring(responseText.indexOf("backupfile:")+11,responseText.indexOf("\n", responseText.indexOf("backupfile:")));
displayMessage(bidix.upload.messages.backupSaved,bidix.dirname(url)+'/'+backupfile);
}
var destfile = responseText.substring(responseText.indexOf("destfile:")+9,responseText.indexOf("\n", responseText.indexOf("destfile:")));
displayMessage(bidix.upload.messages.mainSaved,bidix.dirname(url)+'/'+destfile);
store.setDirty(false);
log.endUpload("ok");
} else {
alert(bidix.upload.messages.mainFailed);
displayMessage(bidix.upload.messages.mainFailed);
log.endUpload("failed");
}
};
// do uploadMain
var revised = bidix.upload.updateOriginal(original,posDiv);
bidix.upload.httpUpload(uploadParams,revised,callback,uploadParams);
};
bidix.upload.httpUpload = function(uploadParams,data,callback,params)
{
var localCallback = function(status,params,responseText,url,xhr) {
url = (url.indexOf("nocache=") < 0 ? url : url.substring(0,url.indexOf("nocache=")-1));
if (xhr.status == httpStatus.NotFound)
alert(bidix.upload.messages.storePhpNotFound.format([url]));
if ((bidix.debugMode) || (responseText.indexOf("Debug mode") >= 0 )) {
alert(responseText);
if (responseText.indexOf("Debug mode") >= 0 )
responseText = responseText.substring(responseText.indexOf("\n\n")+2);
} else if (responseText.charAt(0) != '0')
alert(responseText);
if (responseText.charAt(0) != '0')
status = null;
callback(status,params,responseText,url,xhr);
};
// do httpUpload
var boundary = "---------------------------"+"AaB03x";
var uploadFormName = "UploadPlugin";
// compose headers data
var sheader = "";
sheader += "--" + boundary + "\r\nContent-disposition: form-data; name=\"";
sheader += uploadFormName +"\"\r\n\r\n";
sheader += "backupDir="+uploadParams[3] +
";user=" + uploadParams[4] +
";password=" + uploadParams[5] +
";uploaddir=" + uploadParams[2];
if (bidix.debugMode)
sheader += ";debug=1";
sheader += ";;\r\n";
sheader += "\r\n" + "--" + boundary + "\r\n";
sheader += "Content-disposition: form-data; name=\"userfile\"; filename=\""+uploadParams[1]+"\"\r\n";
sheader += "Content-Type: text/html;charset=UTF-8" + "\r\n";
sheader += "Content-Length: " + data.length + "\r\n\r\n";
// compose trailer data
var strailer = new String();
strailer = "\r\n--" + boundary + "--\r\n";
data = sheader + data + strailer;
if (bidix.debugMode) alert("about to execute Http - POST on "+uploadParams[0]+"\n with \n"+data.substr(0,500)+ " ... ");
var r = doHttp("POST",uploadParams[0],data,"multipart/form-data; boundary="+boundary,uploadParams[4],uploadParams[5],localCallback,params,null);
if (typeof r == "string")
displayMessage(r);
return r;
};
// same as Saving's updateOriginal but without convertUnicodeToUTF8 calls
bidix.upload.updateOriginal = function(original, posDiv)
{
if (!posDiv)
posDiv = locateStoreArea(original);
if((posDiv[0] == -1) || (posDiv[1] == -1)) {
alert(config.messages.invalidFileError.format([localPath]));
return;
}
var revised = original.substr(0,posDiv[0] + startSaveArea.length) + "\n" +
store.allTiddlersAsHtml() + "\n" +
original.substr(posDiv[1]);
var newSiteTitle = getPageTitle().htmlEncode();
revised = revised.replaceChunk("<title"+">","</title"+">"," " + newSiteTitle + " ");
revised = updateMarkupBlock(revised,"PRE-HEAD","MarkupPreHead");
revised = updateMarkupBlock(revised,"POST-HEAD","MarkupPostHead");
revised = updateMarkupBlock(revised,"PRE-BODY","MarkupPreBody");
revised = updateMarkupBlock(revised,"POST-SCRIPT","MarkupPostBody");
return revised;
};
//
// UploadLog
//
// config.options.chkUploadLog :
// false : no logging
// true : logging
// config.options.txtUploadLogMaxLine :
// -1 : no limit
// 0 : no Log lines but UploadLog is still in place
// n : the last n lines are only kept
// NaN : no limit (-1)
bidix.UploadLog = function() {
if (!config.options.chkUploadLog)
return; // this.tiddler = null
this.tiddler = store.getTiddler("UploadLog");
if (!this.tiddler) {
this.tiddler = new Tiddler();
this.tiddler.title = "UploadLog";
this.tiddler.text = "| !date | !user | !location | !storeUrl | !uploadDir | !toFilename | !backupdir | !origin |";
this.tiddler.created = new Date();
this.tiddler.modifier = config.options.txtUserName;
this.tiddler.modified = new Date();
store.addTiddler(this.tiddler);
}
return this;
};
bidix.UploadLog.prototype.addText = function(text) {
if (!this.tiddler)
return;
// retrieve maxLine when we need it
var maxLine = parseInt(config.options.txtUploadLogMaxLine,10);
if (isNaN(maxLine))
maxLine = -1;
// add text
if (maxLine != 0)
this.tiddler.text = this.tiddler.text + text;
// Trunck to maxLine
if (maxLine >= 0) {
var textArray = this.tiddler.text.split('\n');
if (textArray.length > maxLine + 1)
textArray.splice(1,textArray.length-1-maxLine);
this.tiddler.text = textArray.join('\n');
}
// update tiddler fields
this.tiddler.modifier = config.options.txtUserName;
this.tiddler.modified = new Date();
store.addTiddler(this.tiddler);
// refresh and notifiy for immediate update
story.refreshTiddler(this.tiddler.title);
store.notify(this.tiddler.title, true);
};
bidix.UploadLog.prototype.startUpload = function(storeUrl, toFilename, uploadDir, backupDir) {
if (!this.tiddler)
return;
var now = new Date();
var text = "\n| ";
var filename = bidix.basename(document.location.toString());
if (!filename) filename = '/';
text += now.formatString("0DD/0MM/YYYY 0hh:0mm:0ss") +" | ";
text += config.options.txtUserName + " | ";
text += "[["+filename+"|"+location + "]] |";
text += " [[" + bidix.basename(storeUrl) + "|" + storeUrl + "]] | ";
text += uploadDir + " | ";
text += "[[" + bidix.basename(toFilename) + " | " +toFilename + "]] | ";
text += backupDir + " |";
this.addText(text);
};
bidix.UploadLog.prototype.endUpload = function(status) {
if (!this.tiddler)
return;
this.addText(" "+status+" |");
};
//
// Utilities
//
bidix.checkPlugin = function(plugin, major, minor, revision) {
var ext = version.extensions[plugin];
if (!
(ext &&
((ext.major > major) ||
((ext.major == major) && (ext.minor > minor)) ||
((ext.major == major) && (ext.minor == minor) && (ext.revision >= revision))))) {
// write error in PluginManager
if (pluginInfo)
pluginInfo.log.push("Requires " + plugin + " " + major + "." + minor + "." + revision);
eval(plugin); // generate an error : "Error: ReferenceError: xxxx is not defined"
}
};
bidix.dirname = function(filePath) {
if (!filePath)
return;
var lastpos;
if ((lastpos = filePath.lastIndexOf("/")) != -1) {
return filePath.substring(0, lastpos);
} else {
return filePath.substring(0, filePath.lastIndexOf("\\"));
}
};
bidix.basename = function(filePath) {
if (!filePath)
return;
var lastpos;
if ((lastpos = filePath.lastIndexOf("#")) != -1)
filePath = filePath.substring(0, lastpos);
if ((lastpos = filePath.lastIndexOf("/")) != -1) {
return filePath.substring(lastpos + 1);
} else
return filePath.substring(filePath.lastIndexOf("\\")+1);
};
bidix.initOption = function(name,value) {
if (!config.options[name])
config.options[name] = value;
};
//
// Initializations
//
// require PasswordOptionPlugin 1.0.1 or better
bidix.checkPlugin("PasswordOptionPlugin", 1, 0, 1);
// styleSheet
setStylesheet('.txtUploadStoreUrl, .txtUploadBackupDir, .txtUploadDir {width: 22em;}',"uploadPluginStyles");
//optionsDesc
merge(config.optionsDesc,{
txtUploadStoreUrl: "Url of the UploadService script (default: store.php)",
txtUploadFilename: "Filename of the uploaded file (default: in index.html)",
txtUploadDir: "Relative Directory where to store the file (default: . (downloadService directory))",
txtUploadBackupDir: "Relative Directory where to backup the file. If empty no backup. (default: ''(empty))",
txtUploadUserName: "Upload Username",
pasUploadPassword: "Upload Password",
chkUploadLog: "do Logging in UploadLog (default: true)",
txtUploadLogMaxLine: "Maximum of lines in UploadLog (default: 10)"
});
// Options Initializations
bidix.initOption('txtUploadStoreUrl','');
bidix.initOption('txtUploadFilename','');
bidix.initOption('txtUploadDir','');
bidix.initOption('txtUploadBackupDir','');
bidix.initOption('txtUploadUserName','');
bidix.initOption('pasUploadPassword','');
bidix.initOption('chkUploadLog',true);
bidix.initOption('txtUploadLogMaxLine','10');
/* don't want this for tiddlyspot sites
// Backstage
merge(config.tasks,{
uploadOptions: {text: "upload", tooltip: "Change UploadOptions and Upload", content: '<<uploadOptions>>'}
});
config.backstageTasks.push("uploadOptions");
*/
//}}}
bat files are a convenient way on Windows to launch Python modules, using a specific version of Python.
A very simple example:
{{{
@echo off
rem My super awesome bat file
start c:\path\to\pythonw.exe -m someModuleName
}}}
Note, the {{{start}}} will cause the command shell to go away after execution, and we're lauhcing python''w''.exe, to also launch without a separate Python shell.
While you can configure a double-clicked Python .pyw module to call to pythonw.exe via the RMB menu on that icon, that's a clunky step to make all your users too. Bat files are a pretty foolproof way to do this if it helps.
{{{pathlib}}} is OO pathing in Python.
Ships with the 3.4+ standard lib,
Or you can install {{{pathlib2}}} for Python 2: https://pypi.org/project/pathlib2/
* Python 2 docs: https://cpython-test-docs.readthedocs.io/en/latest/library/pathlib.html
* Python 3 docs: https://docs.python.org/dev/library/pathlib.html
Also:
* [[Correspondence to tools in the os module|https://docs.python.org/dev/library/pathlib.html#correspondence-to-tools-in-the-os-module]]
Bunch of simple examples:
{{{
try:
from pathlib2 import Path # Python 2
except ImportError:
from pathlib import Path # python 3
}}}
{{{
# Initial creation
p1 = Path(r"c:\temp")
p2 = Path("c:/Temp/")
}}}
{{{
# Concatenate
p3 = p2 / 'notAFile.txt'
print p3
# c:\Temp\notAFile.txt
print p1.joinpath("spam", "eggs")
# c:\temp\spam\eggs
}}}
{{{
# Comparison
print p1 == p2
# True
}}}
{{{
# Printing
print `p1`
# WindowsPath('c:/temp')
print p2
# c:\Temp
print p3
# c:\Temp\notAFile.txt
}}}
{{{
# Querying files in directory by type:
print list(p1.glob("*.log")) # glob returns Generator
# [WindowsPath('c:/temp/errorLog.log'), WindowsPath('c:/temp/mainLog.log')]
}}}
{{{
# Query existance
print p1.exists()
# True
print p3.exists()
# False
}}}
{{{
# Query type:
print p1.is_dir()
# True
print p1.is_file()
# False
}}}
{{{
# Create Directory: Note, this only works if the parent dir already exists.
if not p1.exists():
p1.mkdir()
}}}
{{{
# Open a file:
with list(p1.glob("*.log"))[0].open() as f: f.readline()
# Result: u'2020-02-26 14:02:21,588 : WARNING : Errorlog: Warning message.\n' #
}}}
{{{
# Query parts of the path:
print p3.parts
# ('c:\\', 'Temp', 'notAFile.txt')
print p3.parents[0] # Count backwards
# c:\Temp
print p3.parents[1]
# c:\
print p3.parent
# c:\Temp
print p1.name
# temp
print p3.name
# notAFile.txt
print p3.suffix
# .txt
print p2.suffix
# <- nothing
print p3.stem
# notAFile
print p3.drive
# c:
print p3.anchor
# c:\
}}}
{{{
# Working relative to current module
thisFile = Path(__file__)
thisDir = thisFile.parent
# or
thisDir = thisFile.parents[0]
parentDir = thisDir.parent
# or
parentDir = thisFile.parents[1]
}}}
{{{
# Check relativity.
print p3.relative_to(p1)
# The part of p3 that is relative to p1:
# notAFile.txt
}}}
{{{
# Changing filename / suffix
print p3.with_name("spam.txt")
# c:\Temp\spam.txt
print p3.with_suffix(".eggs")
# c:\Temp\notAFile.eggs
}}}
https://www.voidtools.com/support/everything/sdk/
https://www.voidtools.com/support/everything/sdk/python/
Python docs on this subject are found in the [[site|http://docs.python.org/library/site.html]] module.
The {{{site}}} module is automatically imported when Python launches (this can be suppressed). From the docs, "Importing this module will append site-specific paths to the module search path and add a few builtins." This includes the parsing of {{{.pth}}} files (see notes [[here|How can I set Python's path?]]).
After all that happens, from the docs:
<<<
After these path manipulations, an attempt is made to import a module named {{{sitecustomize}}}, which can perform arbitrary site-specific customizations. It is typically created by a system administrator in the site-packages directory. If this import fails with an ~ImportError exception, it is silently ignored.
<<<
Then
<<<
After this, an attempt is made to import a module named {{{usercustomize}}}, which can perform arbitrary user-specific customizations, if {{{site.ENABLE_USER_SITE}}} is true (which it is by default). This file is intended to be created in the user site-packages directory (see below), which is part of {{{sys.path}}} unless disabled by -s. An {{{ImportError}}} will be silently ignored.
<<<
Which means, if you have {{{sitecustomize.py}}} or {{{usercustomize.py}}} modules somewhere in your path, they will be automatically imported when Python launches. This is a great way to have code you always want ran executed when Python launches.
Conceptually, {{{sitecustomize}}} would be be a team-wide module, that everyone shares, while {{{usercustomize}}} is available for the individual user to modify and make use of.
----
Also see:
*[[How can I have Python execute a module before it starts?]]
*[[How can I append to Python's site-packages dir?]]
Python seems to have no built in libraries for doing vector math. I've done some research into external libraries [[here|Are there vector math libraries in Python?]].
Based on a pile of info I got from the below website, I made a few functions to do this without the overhead of the external libraries. This is not an exhaustive list of vector functions, just some of the more popular ones.
http://www.geocities.com/SiliconValley/2151/math3d.html
http://mathworld.wolfram.com/topics/VectorAlgebra.html
http://en.wikipedia.org/wiki/Euclidean_vector
[[Autodesk University: ICE Design Tools|http://area.autodesk.com/userdata/blogs/marks/ToddAkita_ICE_Design_Tools.pdf]] (pdf) - This is for Softimage's ICE, but the reference it has for trig and vectors is great.
{{{
import math
vec1 = [1,0,0]
vec2 = [0,1,0]
point1 = [0,0,0]
point2 = [0,1,0]
point3 = [1,0,0]
def mag(vector):
"""
Return the length of a vector.
"""
val = 0
for v in vector:
val += pow(v,2)
m = math.sqrt(val)
return m
def unit(vector):
"""
Find unit vector.
Vector if length = 1
"""
len= mag(vector)
u = [vec/len for vec in vector]
return u
def dot(v1, v2):
"""
Find dot product of two vectors
Easy description: If v1 & v2 are pointing the same direction, this value
is 1.0. If they're pointing opposite directions, this value is -1. If they
are at right angles, the value is 0. So you can use this test to see how well
two vectors align.
More complex description:
It can be interpreted as the *length* of the projection of
the unit of v1 onto v2 when the two vectors are placed so that
their tails coincide.
http://mathworld.wolfram.com/DotProduct.html
Your right index finger is V1, your left index finger is V2. Place
both knuckles on top of one another, pointing in different directions.
Find the unit vector of V1 (right finger), and mark that point on your
right finger. Then...
Draw a perpendicular line from the mark on your right finger (V1) to your
left finger (V2), and mark a second point. The dot product is the distance
from your left knuckle to that second point. GOT IT?
"""
v1 = unit(v1)
v2 = unit(v2)
d=0
for i in range(len(v1)):
d = d + v1[i]*v2[i]
return d
def cross(v1, v2):
"""
Find cross product of two vectors.
Vector which is perpendicular to the two.
"""
v = [v1[1]*v2[2] - v1[2]*v2[1],
v1[2]*v2[1] - v1[1]*v2[2],
v1[0]*v2[1] - v1[1]*v2[0]]
return v
def normal(p1, p2, p3):
"""Given three 3d points, find the vector normal to those points"""
va = [p1[0] - p2[0], p1[1] - p2[1], p1[2] - p2[2]]
vb = [p3[0] - p2[0], p3[1] - p2[1], p3[2] - p2[2]]
n = cross(va, vb)
return n
def sum(v1, v2):
"""
Add two vectors together
"""
ret = []
for i in range(len(v1)):
ret.append(v1[i] + v2[i])
return ret
def difference(v1, v2):
"""
Subtract v2 from v1.
"""
ret = []
for i in range(len(v1)):
ret.append(v1[i] - v2[i])
return ret
print "Length vec1:", mag(vec1)
print "Unit vec1:", unit(vec1)
print "Dot vec1, vec2:", dot(vec1, vec2)
print "Cross vec1, vec2:", cross(vec1, vec2)
print "Normal of point1, point2, point3:", normal(point1, point2, point3)
print "Sum of vec1, vec2:", sum(vec1, vec2)
print "Difference of vec1, vec2:", difference(vec1, vec2)
# Length vec1: 1.0
# Unit vec1: [1.0, 0.0, 0.0]
# Dot vec1, vec2: 0
# Cross vec1, vec2: [0, 0, 1]
# Normal of point1, point2, point3: [0, 0, 1]
# Sum of vec1, vec2: [1, 1, 0]
# Difference of vec1, vec2: [1, -1, 0]
}}}
http://www.virtualenv.org/
! My High Level Notes
* Appears to come standard in Python3.6+(?)
* Similar to distribution managers like [[Anaconda Fundamentals]]
* Allows you to create a whole bunch of separate independent Python installs by version, collecting different packages.
* Allows you to pair version of Python (2.x, 3.x, 32-bit, 64-bit) with different versions of modules, that may have dependency issues.
* To use different versions of Python in different venvs:
** Download/install the various versions of Python.
** When making a new venv (shown below), if you want to use a certain python.exe, then provide that full path to the exe when creating the venv. Simple example, to make a venv for Python 3.8, 32bit, I call it 'py_38_32'
** When you {{{activate.bat}}} and run Python, that version should now be active.
!Tutorials:
* https://docs.python.org/3/tutorial/venv.html
* http://dabapps.com/blog/introduction-to-pip-and-virtualenv-python/
! Notes
* A common root for your environments is:
{{{
C:\Users\USERNAME\Documents\venv
}}}
To create a new venv (remember, the version of python you execute it with is the version of python it will use)
{{{
> cd C:\Users\USERNAME\Documents\venv
> python -m venv my-venv-name
> cd C:\Users\USERNAME\Documents\venv\my-venv-name\Scripts
> activate.bat
}}}
This will then change the command prompt for that shell to show you which venv you're in:
{{{
(my-venv-name) C:\Users\USERNAME\Documents\venv\my-venv-name\Scripts
}}}
You can use {{{deactivate.bat}}} in the same folder to 'turn it off'.
Each env comes with its own pip, so use it to install new packages:
{{{
> C:\Users\USERNAME\Documents\venv\my-venv-name\Scripts\pip.exe install newPackage
}}}
See: [[Installing Python Packages]] (pip)
I find it helpful when making UI's to have a visual guide to go off of. Below is a visual guide of various Tkinter widgets. I won't say this is exhaustive, but I'll update it as I find new ones. I pulled the majority of these from the examples listed here:
http://effbot.org/tkinterbook/tkinter-index.htm#class-reference
The module I made to make all of these examples is located here:
http://www.akeric.com/python/TkImages/TkWidgets.py
----
[img[http://www.akeric.com/python/TkImages/BitmapImage.jpg]]
[img[http://www.akeric.com/python/TkImages/Button.jpg]]
[img[http://www.akeric.com/python/TkImages/Canvas.jpg]]
[img[http://www.akeric.com/python/TkImages/Checkbutton.jpg]]
[img[http://www.akeric.com/python/TkImages/Entry.jpg]]
[img[http://www.akeric.com/python/TkImages/Frame.jpg]]
[img[http://www.akeric.com/python/TkImages/Label.jpg]]
[img[http://www.akeric.com/python/TkImages/LabelFrame.jpg]]
[img[http://www.akeric.com/python/TkImages/Listbox.jpg]]
[img[http://www.akeric.com/python/TkImages/Menu.jpg]]
[img[http://www.akeric.com/python/TkImages/Message.jpg]]
[img[http://www.akeric.com/python/TkImages/OptionMenu.jpg]]
[img[http://www.akeric.com/python/TkImages/PanedWindow.jpg]]
[img[http://www.akeric.com/python/TkImages/PhotoImage.jpg]]
[img[http://www.akeric.com/python/TkImages/RadioButton.jpg]]
[img[http://www.akeric.com/python/TkImages/Scale.jpg]]
[img[http://www.akeric.com/python/TkImages/Scrollbar.jpg]]
[img[http://www.akeric.com/python/TkImages/Spinbox.jpg]]
[img[http://www.akeric.com/python/TkImages/Text.jpg]]
One of my co-workers pointed me to this forum:
http://georgia.ubuntuforums.org/showthread.php?p=9543637
The code was a bit buggy to get working off the bat (based on how they import PIL), but once we got it working it had some good results.
Moar:
*http://code.activestate.com/recipes/577353-voronoi-diagram/
*http://jtauber.com/blog/2008/11/07/voronoi_diagrams/
*http://code.activestate.com/recipes/578459-worley-noise-generator/
<<gradient horiz #ffffff #ddddff #8888ff>>
[img[warpcat|http://farm3.static.flickr.com/2017/2118148943_75636dd96c.jpg?v=0]] Yes, that is me playing [[Rock Band|http://www.rockband.com/]].
''Eric Pavey''
*Email: - warpcat {{{(at)}}} sbcglobal {{{(dot)}}} net -
*[[Blog|http://www.akeric.com/blog/]] - [[LinkedIn|http://www.linkedin.com/in/pavey]] - [[Flickr|http://www.flickr.com/photos/8064698@N03/collections/]] - [[Youtube|http://www.youtube.com/profile?user=warpcat]] - [[MobyGames|http://www.mobygames.com/developer/sheet/view/developerId,76979/]] - [[Instagram|https://instagram.com/e_pavey/]]
>>
My other Tiddlywiki's:
*[[PyGame wiki|http://pygamewiki.tiddlyspot.com/]]
*[[mel wiki|http://mayamel.tiddlyspot.com/]]
*[[Processing wiki|http://processingwiki.tiddlyspot.com/]]
*[[CG OpenSource wiki|http://cgoswiki.tiddlyspot.com/]]
<<gradient horiz #ffffff #ddddff #8888ff >>
[[About python tiddlywiki]] (go here first)
[[Instructions for use]] (go here second)
[[Check out the latest updates|History]] (go here third. //Hit ''F5'' to refresh your cache to see latest stuff.//)
<<gradient horiz #ddddff #8888ff >>''Browse \ Search using:''
----
{{{<---}}} Major ''//Categories//'' (or 'All Subjects') in the Left column
Key-word ''//Tags//'' tab in the Right column (press Ctrl+f to open your browsers search) {{{--->}}}
----
>>>>
^^Running [[tiddlywiki|http://www.tiddlywiki.com]] v<<version>>^^
^^If you find this wiki useful, let the [[author|WarpCat]] know!^^
[[Copyright Information|Copyright Information]]
+
*{{{PYTHONPATH}}}
*{{{PYTHONSTARTUP}}} : If set to the name of a readable file, the Python commands in that file are executed before the first prompt is displayed in interactive mode
*{{{PYTHONHOME}}}
*{{{PYTHONCASEOK}}}
*{{{PYTHONDEBUG}}}
*{{{PYTHONINSPECT}}}
*{{{PYTHONOPTIMIZE}}}
*{{{PYTHONBUFFERED}}}
*{{{PYTHONVERBOSE}}}
Find by code:
{{{
import types
for d in dir(types):
print d
}}}
prints:
{{{
BooleanType
BufferType
BuiltinFunctionType
BuiltinMethodType
ClassType
CodeType
# ...
}}}
This is by no means an exhaustive list, but it covers most of the basics. Each type is an //object//, that a variable can point to.
http://docs.python.org/library/types.html#l2h-858
http://docs.python.org/reference/datamodel.html#the-standard-type-hierarchy
http://docs.python.org/library/stdtypes.html
{{{
print type(True)
# <type 'bool'>
print type(33)
# <type 'int'>
print type(33L)
#<type 'long'>
print type(3.33)
#<type 'float'>
print type(3.33J)
# <type 'complex'>
print type("thirtyThree")
# <type 'str'>
print type(u"thirtyThree")
# <type 'unicode'>
print type([3.33, "three"])
# <type 'list'>
print type((3.33, "three"))
# <type 'tuple'>
print type({"three" : 3})
# <type 'dict'>
print type(open(myFile))
# <type 'file'>
print type(set('three'))
# <type 'set'>
print type(type)
# <type 'type'>
print type(None)
# <type 'NoneType'>
import datetime
print type(datetime)
# <type 'module'>
from decimal import Decimal
print type(Decimal('3.33'))
# <class 'decimal.Decimal'>
def func():
pass
print type(func)
# <type 'function'>
print type(lambda x:x)
# <type 'function'>
class MyObj(object):
pass
print type(MyObj)
# <type 'type'>
print type(MyObj())
# <class '__main__.MyObj'>
}}}
Also see:
*[[How are Pythons built-in types organized?]]
''All very WIP. Just a starting point''
----
In the interactive command line. Pretty much the simplest way:
{{{
c:\Python25>Python
Python 2.5.2 (r252:60911, Feb 21 2008, 13:11:45) [MSC v.1310 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> print "spam!"
spam!
>>>
}}}
Same thing can be done via an [[IDE's|Wing IDE]] interactive commandline obviously.
----
On Windows, double-clicking a .py file
----
In a module, [[import]]ing a module the first time will execute any code in it, not defined as a function. Subsequent imports won't execute the code. If you want to re-execute it, you need to {{{reload}}} it.
----
http://www.alobbs.com/pykyra
''~PyKyra'': "a fast game development framework for Python"
----
http://www.pygame.org
"''Pygame'' is a set of Python modules designed for writing games. Pygame adds functionality on top of the excellent [[SDL library|http://www.libsdl.org/]]. This allows you to create fully featured games and multimedia programs in the python language. Pygame is highly portable and runs on nearly every platform and operating system."
*[[Pygame Documentation|http://www.pygame.org/docs/]]
*''I have started my own 'PyGame wiki' here: http://pygamewiki.tiddlyspot.com/''
----
http://www.livewires.org.uk/python/home
"The ''~LiveWires'' Python Course is intended to teach the Python programming language to people who have never programmed before."
You can consider ~LiveWires a wrapper for Pygame, to reduce the complexity.
It is a function annotation: https://www.python.org/dev/peps/pep-3107
From:
https://stackoverflow.com/questions/31445728/what-does-the-dash-greater-than-arrow-symbol-mean-in-a-python-method-signat
"This is function annotations. It can be use to attach additional information to the arguments or a return values of functions. It is a useful way to say how a function must be use. Functions annotations are stored in a function's {{{__annotations__}}} attribute."
If you're like me, at a certain point in my life I didn't know much about xml, or DOM objects (and of this writing, I still don't know that much).
DOM stands for '''Document Object Model'''. Couple of links:
http://en.wikipedia.org/wiki/Document_Object_Model
http://www.w3.org/DOM/
>The Document Object Model is a platform- and language-neutral interface that will allow programs and scripts to dynamically access and update the content, structure and style of documents. The document can be further processed and the results of that processing can be incorporated back into the presented page.
From they [[Python Docs|http://www.python.org/doc/current/lib/module-xml.dom.html]]:
>The Document Object Model, or 'DOM', is a cross-language API from the World Wide Web Consortium ([[W3C|http://www.w3.org/]]) for accessing and modifying XML documents. A DOM implementation presents an XML document as a tree structure, or allows client code to build such a structure from scratch. It then gives access to the structure through a set of objects which provided well-known interfaces.
Some good tutorials for XML over at [[W3Schools|http://www.w3schools.com/default.asp]]
Example code:
{{{
class Foo(object):
def __init__(self, namer, num):
self.name = namer
self.number = num
# etc...
# then, when building the object:
myObject = Foo("doof", 3)
}}}
*You create an object by instancing the class by calling to the //constructor method// (which is the {{{__init__}}} method). It takes at minimum, one argument, which is a string {{{self}}}. What IS {{{self}}}? The {{{self}}} parameter represents the object 'itself', the object that you created when instancing the class. It provides a way for a method to refer to the object itself.
*The actual string '{{{self}}}' can really be anything as long as it's consistent, but in Python everyone uses {{{self}}}. For example, in the language Processing (which is higher-level a wrapper for Java), they use the term '{{{this}}}' when making their objects.
*When you call to make a new object, {{{self}}} //becomes// the name of the new object (from the above example) "{{{myObject}}}". So again, from the example, {{{self}}} = "{{{myObject}}}"! In a sense, the constructor method {{{__init__}}} 'takes in' the name {{{myObject}}}, and inserts it into argument {{{self}}}. Considering that, you could //conceptually visualize// the example from above as such:
{{{
# substitute 'self' for the user defined object name 'myObject':
def __init__(myObject, namer, num):
myObject.name = namer
myObject.number = num
# etc...
}}}
Fore more info on classes, see [[Class]] and [[Class - advanced]]
What's faster when doing power/exponent math: The {{{pow}}} func, the {{{**}}} operator, or just multiplying?
{{{
now = time.time()
for i in range(100000):
pow(4, 4)
later = time.time()
print "pow took %s secs"%str(later-now)
now = time.time()
for i in range(100000):
4**4
later = time.time()
print "** took %s secs"%str(later-now)
now = time.time()
for i in range(100000):
4*4*4*4
later = time.time()
print "4*4*4*4 took %s secs"%str(later-now)
}}}
So, for the hundred-thousand loops, it took this long on my Macbook Air:
{{{
pow took 0.213723182678 secs
** took 0.164659023285 secs
4*4*4*4 took 0.166641950607 secs
}}}
So it looks like the winner is the {{{**}}} operator, at least on my machine ;)
Updated note:
<<<
After sitting in a cave for a week meditating on this subject, I came up with something that helped me understand it better:
*If when you see@@ {{{__name__}}}@@, you replace it with '@@[[namespace]]@@', it seems to give the concepts that surround a bit more clarity.
Basically, the {{{__name__}}} attribute holds the name of the current namespace for the given object.
In the below examples try it, and I'll think you'll agree...
<<<
----
Sometimes you'll see this a the bottom of some modules:
{{{
if __name__ == "__main__":
# do some code
}}}
When you see things with double-underscores "{{{__}}}" on either side of their name, these refer to 'special attributes'. So given an module called {{{foo.py}}}, it has a special attribute called {{{foo.__name__}}}. If you //[[import]]// that module into a different module, {{{foo.__name__}}} will end up equaling the name of the module, "{{{foo}}}" :
{{{
import foo
print foo.__name__
foo
}}}
However, if {{{foo}}} is execute from a shell, not being imported into another module, then it's {{{__name__}}} attribute ends up equaling "{{{__main__}}}":
{{{
# This is the contents of 'foo.py':
if __name__ == "__main__":
print "foo.__name__ = " + __name__
raw_input("Press Enter to continue")
}}}
And when executed from a shell:
{{{
foo.__name__ = __main__
Press Enter to continue
}}}
__So what's the point of all of this?__ It allows the author to create different behaviors for the module depending on how it's executed. If the module is imported into another one, then nothing special happens. But if the module is executed from a shell, then a cusom UI could pop up, querying the user for input before code execution.
----
Also see:
*[[namespace]]
http://svn.python.org/view/python/trunk/
Coming from the PC side of Python instalation, dealing with it on the Mac seems much more confusing.
(need to check out [[sys.prefix|http://docs.python.org/2/library/sys.html#sys.prefix]] on the Mac)
The Mac comes with Python pre-installed, living under the ''/System'' folder here:
{{{
/System/Library/Frameworks/Python.framework/Versions/
}}}
But there's a good chance it's out of date. I'm currently not sure how these are updated, but they seem to somehow, over time.
You can install your own versions. They'll live in their own location under the ''/Library'' folder:
{{{
/Library/Frameworks/Python.framework/Versions/
}}}
That area is safe to delete.
But there also appears to be an Applications location for each custom install:
{{{
/Applications/Python 2.6
}}}
Which is where the {{{IDLE.app}}} lives
From the above example, the {{{/site-packages}}} dir of a custom Python 2.6 install would live in the below directory. Things installed via [[pip|Installing Python Pacakges]] end up in here:
{{{
/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages
}}}
However... there seems to be YET ANOTHER site-packages dir living here:
{{{
/Library/Python/2.6/site-packages/
}}}
All that being said, where the actual //executable// lives seems to live in an confusing state. See notes on that here:
*[[How can I query the python executable location?]]
{{{
# TypeError: super(type, obj): obj must be an instance or subtype of type #
}}}
If you get this type of error after reloading your modules, it’s because the reload order is wrong: Need to load modules in order of importance : If model B is imported into module A, you need to reload A before B.
Also, see [[Call an overridden superclass method]] for how changes to Python 3 can trigger this without a reload.
SO, some files added to P4 can have illegal characters in their names. They show up as spaces, which are also generally a terrible idea, but they're actually some other crazy character hat looks like this: [[[u'\xa0']|http://www.codetable.net/hex/a0]]
Having P4 even touch these files via the commandline can completely crash it, so we need to skip them.
{{{
from P4 import P4
import string
# Define a string of all good characters that can exist in a path.
# Even though we don't like space, it's still technically permissible.
good = string.ascii_letters + string.digits+"\\/.:_ "
badChars = []
# Notice the space at the end? Its' really [u'\xa0']
f = r"c:\path\to\my\file\badchar .txt"
for char in f:
if char not in good:
badChars.append(char)
if not badChars:
p4 = P4()
p4.connect()
result = p4.run_revert(f)
p4.disconnect()
else:
print "Unable to revert file, has illegal characters: %s"%badChars
}}}
The P4 API counts on certain system-level environment variables to be set to function. If they've never been set, bad things.
If you go to a command shell and type this:
{{{
> p4 set
}}}
You should see something like this (with different values of course)
{{{
P4CLIENT=clientName (set)
P4PORT=portName:1666 (set)
P4USER=yourName (set)
}}}
If you don't, that's probably the problem.
To set these values via ~P4V:
* Connection -> Environment Settings
* Check 'Use current connection for environment settings'
* Press 'OK'
If you open a new shell and run the above command, you should see the vars, and your Python code should start to function.
I've had instance of trying to make ~PySide windows inside of certain apps, like Unreal. When you subclass a widget to make your window, it can crash the application when trying to display.
I've learned that putting this in the {{{__init__}}} method //before// you call to {{{super}}} will fix it:
{{{
if not QtGui.QApplication.instance():
QtGui.QApplication(sys.argv)
}}}
When you install Python from a legit installer, not only does it (by default) copy it to
{{{
C:\Python27
}}}
But it copes a file here:
{{{
C:\Windows\System32\python27.dll
}}}
And updates the Windows PATH to see that dir.
However, if you're trying to distribute Python via version control like P4, just copying the \Python27 folder somewhere else, future uses never get their PATH updated to see the widows dir, and neither do they get that dll at all.
The fix is easy: Simply move that dll into the root Python install folder, add to your version control, all is good.
Seems to be some sort of bug, I've seen this happen in both v4 & v5 now.
The fix is easy: In the Project view, RMB on the root project folder and uncheck 'Auto-update Perforce Status'
Notes on editing wiki:
*[[Add custom graphics to the header|http://www.tiddlywiki.org/wiki/How_To/Header_Macro/Plugin_%28for_Custom_Graphic_Header%29]]
*[[text formatting]]
*[[list of macros|http://www.tiddlywiki.org/wiki/What_macros_are_built_in_to_TiddlyWiki%3F]]
*[[DateFormatString arguments|http://www.tiddlywiki.com/#DateFormatString]]
I've been looking for a LONG time, trying to find an IDE for Python that mirrored //one// important feature from Autodesk Maya's Script Editor: ''Evaluate Selection'', which is the ability to highlight blocks of code, and execute just that block interactively. This is also known as [[REPL|http://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop]].
Maya's implementation of Python in the Script Editor can do this (since version 8.5), but what if you want to author Python //outside// of Maya (like most folks), but still have this functionality?
After asking a lot of people, and doing a lot of searching, I finally found one:
http://www.wingware.com/
It has three versions:
*Wing IDE 101 (free, but //doesn't// have 'Evaluate Selection')
*Wing IDE Personal $
*Wing IDE Professional $
http://www.wingware.com/wingide/features
Simple example, using {{{OrderedDict}}} to hold the data. Note, unfortunately you can't use an {{{OrderedDict}}} as the main dictionary being passed to the json lib: It'll raise an exception saying it can't be serialized :S
Make some data to store as json. Could use regular {{{dict}}} instead of {{{OrderedDict}}} if you don't care about the serialized order.
{{{
from collections import OrderedDict as od
import json
peopleA = od( [ ["name", "fred"],
["mood", "happy"],
["filePath", "c:/blah/fred.stuff"]] )
peopleB = od( [ ["name", "sarah"],
["mood", "sleepy"],
["filePath", "c:/blah/sarah.stuff"]] )
foodA = od([ ["name", "spaghetti"],
["sauce", "red"]])
foodB = od([ ["name", "ice cream"],
["sauce", "chocolate"]])
data = {"metadata":"I am a happy json file",
"people":[ peopleA, peopleB ] ,
"materials":[ foodA, foodB]}
}}}
Save to disk:
{{{
with open("c:/temp/foo.json", mode='w') as f:
json.dump(data, f, indent=2, separators=(',', ' : '))
}}}
Printing the previous data, and loading from disk and printing give the same results:
{{{
d = json.dumps(data , indent=2, separators=(',', ' : '))
# or:
with open("c:/temp/foo.json", mode='r') as f:
d = json.load(f)
print d
{
"people" : [
{
"name" : "fred",
"mood" : "happy",
"filePath" : "c:/blah/fred.stuff"
},
{
"name" : "sarah",
"mood" : "sleepy",
"filePath" : "c:/blah/sarah.stuff"
}
],
"materials" : [
{
"name" : "spaghetti",
"sauce" : "red"
},
{
"name" : "ice cream",
"sauce" : "chocolate"
}
],
"metadata" : "I am a happy json file"
}
}}}
https://docs.python.org/2/library/json.html
As an alternative to {{{xml.dom.minidom}}} (since it seems so clunky), notes on {{{ElementTree}}}.
Docs:
*http://docs.python.org/library/xml.etree.elementtree.html
*http://effbot.org/zone/element.htm (nice tutorials, go read this now)
*http://blog.doughellmann.com/2010/03/pymotw-parsing-xml-documents-with.html
{{{
import xml.etree.ElementTree as ET
}}}
''Examples:''
----
Search some xml on disk called foo.xml
In it, find the first child element of the root called "firstTagElement"
Under that, find all elements (could be more than one) that are called "subTagElement"
If none of those sub-elements have the text defined by {{{searchText}}}, then add a new sub-element, with that text.
And save to disk (and print)
{{{
import xml.etree.ElementTree as ET
xmlPath = "c:/temp/foo.xml"
searchText = "addMe"
noMatch = 1
tree = ET.parse(xmlPath)
root = tree.getroot()
firstTagElement = root.find("firstTagElement")
for subElement in firstTagElement.findall("subTagElement"):
if subElement.text == searchText:
noMatch = 0
break
if noMatch:
element = ET.SubElement(firstTagElement ,"subTagElement")
element.text = searchText
tree.write(xmlPath, "UTF-8")
# or:
print ET.tostring(root)
}}}
The xml being searched (before modification) could look like this:
{{{
<?xml version="1.0" encoding='UTF-8'?>
<root>
<firstTagElement>
<subTagElement>some text</subTagElement>
<subTagElement>some more text</subTagElement>
</firstTagElement>
</root>
}}}
After modification and save:
(Actually, this is a lie, it's formatting will be screwed up. Please see my notes here: [[Poorly formatted xml problems]])
{{{
<?xml version="1.0" encoding='UTF-8'?>
<root>
<firstTagElement>
<subTagElement>some text</subTagElement>
<subTagElement>some more text</subTagElement>
<subTagElement>add me</subTagElement>
</firstTagElement>
</root>
}}}
----
Note #1: This is mainly a scratchpad until I figure out what the heck I'm doing...
Note #2: I found minidom to be a real pain, and have mainly switched to ~ElementTree. Check out my docs here: [[Working with xml and ElementTree]]
----
Online Examples:
*http://acaciaecho.wordpress.com/2011/04/02/python-xml-basic/
----
In this simple example, an xml file is loded into a dom, and then it is searched:
First, it finds all {{{tags}}} ({{{elements}}}) with the name "material".
Then, for each of those {{{tags}}}, it finds the value of the {{{attribute}}} "id", and prints them.
{{{
import xml.dom.minidom
doc = r"c:\temp\some.xml"
mDom= xml.dom.minidom.parse(doc)
for i in mDom.getElementsByTagName("material"):
# Find the value of attribute "id" under tag "material":
print i.getAttribute("id")
# Set the value of attribute "foo" under tag "material":
i.setAttribute("foo", "someVal")
}}}
Find the root tag value:
{{{
print mDom.documentElement.tagName
}}}
Make a //new// dom object from scratch.
{{{
import xml.dom.minidom
impl = xml.dom.minidom.getDOMImplementation()
newdoc = impl.createDocument(None, "ROOT", None)
top_element = newdoc.documentElement
text = newdoc.createTextNode('Some data')
top_element.appendChild(text)
ft = newdoc.createElement("firstTag")
top_element.appendChild(ft)
attr = newdoc.createAttribute("someAttr")
ft.setAttributeNode(attr)
print newdoc.toprettyxml()
}}}
{{{
<?xml version="1.0" ?>
<ROOT>
Some data
<firstTag someAttr=""/>
</ROOT>
}}}
Make a new dom object from a pre-exsting xml file or string. Both functions return a {{{Document}}} object representing the content of the document.
{{{
# from a file:
xml.dom.minidom.parse
# from a string:
xml.dom.minidom.parseString
}}}
If you want to query they type of node a node is:
{{{
nt = Node.nodeType
}}}
And you can compare that against the list of valid node types:
http://docs.python.org/library/xml.dom.html#xml.dom.Node.nodeType
Presuming you already have a element, how can you find the text of it?
{{{
for tag in self.mDom.getElementsByTagName("someTag"):
for cn in tag.childNodes:
if cn.nodeType == cn.TEXT_NODE:
print cn.data
}}}
That seems like a lot of effort to find the "text"
----
Sometimes (all the time?) when I parse a pre-existing xml and add new elements, when I write out the xml, the formatting gets all screwed up for the elements I add. It has to do with the fact that new return characters are introduced in addition to the pre-existing ones. Here's a solution to help solve for this, but it can modify the formatting of the original xml:
{{{
xmlText = mDom.toxml("UTF-8")
lines = xmlText.split("\n")
writer = [i for i in lines if len(i.rstrip()) != 0]
for j in writer:
print j
}}}
----
Based on the above examples:
*minidom docs:
**http://docs.python.org/library/xml.dom.minidom.html
*If you want to process the '{{{Document}}} object' you can uses these commands:
**http://docs.python.org/library/xml.dom.html#document-objects
*If you want to process an '{{{Element}}} object' from the dom (the object returned from one of the above commands):
**http://docs.python.org/library/xml.dom.html#element-objects
*If you want to process an '{{{Atribute}}} object':
**http://docs.python.org/library/xml.dom.html#attr-objects
*For any node object, here is info you can pull from it:
**http://docs.python.org/library/xml.dom.html#node-objects
----
Given a simple xml file '{{{note.xml}}}':
{{{
<?xml version="1.0" encoding="ISO-8859-1"?>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
}}}
Load it in Python, and then print it:
{{{
from xml.dom import minidom
DOMTree = minidom.parse("note.xml")
print DOMTree.toxml()
}}}
(prints the above xml...)
----
Another Example:
{{{
import xml.dom.minidom
doc = """\
<?xml version="1.0" encoding="ISO-8859-1"?>
<tagA>
<tagB tagB_attr="tagB attr value"> tagB text </tagB>
<tagC tagC_attr="tagC attr value"> tagC text </tagC>
</tagA>
"""
dom = xml.dom.minidom.parseString(doc)
childNodes = dom.childNodes
nodeList = childNodes[0].getElementsByTagName("tagC")
for n in nodeList:
print n.toxml()
# <tagC tagC_attr="tagC attr value"> tagC text </tagC>
}}}
The above example accesses a string directly as a xml file via the {{{.parseString()}}} method. Then using the {{{.getElementsByTagName()}}} method, we search for //all// child elements with the tag name {{{tagC}}}.
----
{{{minidom.parse}}} creates {{{Document}}} object. Then you can call the {{{.toxml()}}} method which returns a string containing the text from the xml.
----
Python docs for {{{xml.dom}}}:
http://www.python.org/doc/current/lib/module-xml.dom.html
Docs for {{{xml.dom.minidom}}}:
http://docs.python.org/lib/module-xml.dom.minidom.html
{{{minidom}}} examples:
http://docs.python.org/lib/dom-example.html
----
All of the below docs call to attributes and methods that can act on the objects created by {{{minidom.parse()}}}:
Docs for {{{DOM}}} objects:
http://docs.python.org/lib/dom-objects.html
Docs for {{{Node}}} objects:
http://docs.python.org/lib/dom-node-objects.html
Docs for {{{Document}}} objects:
http://docs.python.org/lib/dom-document-objects.html
I have other subjects on these, so why not make another one! As I continue to try to pick apart how all of these relate :)
*http://docs.python.org/library/__main__.html
*http://docs.python.org/library/__builtin__.html
Notes on {{{__builtins__}}}:
*http://mail.python.org/pipermail/python-dev/2005-December/058652.html
*http://mail.python.org/pipermail/python-3000/2007-March/006161.html
----
*{{{__main__}}} is the most top level [[scope|Python variable scope]] in Python.
*{{{__builtin__}}} is a module, that has all the 'built-in' python functions you use.
*{{{__builtins__}}} //appears// to be a [[namespace]] that {{{__builtin__}}} is imported into during Python launch, giving you access to all of {{{__builtin__}}} functions (this is a //theory// of mine). This allows you (again, theory) to call to them without having to fully quality them, like:
<<<
{{{
# If __builtin__ *wasn't* imported into __builtins__,
# you'd need to do stuff like this:
import __builtin__
stuff = __builtin__.sorted(foo)
}}}
{{{
# But since __builtins__ is by default imported into __main__,
# we can do stuff like this instead:
stuff = sorted(foo)
}}}
<<<
*And from one of the links on {{{__builtins__}}} above, I think this is a good analysis:
<<<
In module {{{__main__}}}:
*{{{__builtins__}}} is a reference to module {{{__builtin__}}}.
*{{{__builtin__}}} only exists if you import it.
In any other module:
*{{{__builtins__}}} is a reference to module {{{__builtin__}}}'s {{{__dict__}}}.
*{{{__builtin__}}} only exists if you import it.
<<<
----
Let's illustrate this in action:
Make a module called {{{scopeTest.py}}}:
{{{
# scopeTest.py
def scopeTestMain():
# Print everything in the __main__ namespace
import __main__
for m in sorted(__main__.__dict__):
print m
def scopeTestBuiltin():
# Print everything in the __builtin__ module
import __builtin__
for bi in sorted(__builtin__.__dict__):
print bi
def scopeTestBuiltins():
# Print everything in the __builtins__ namespace
import __main__
for bis in sorted(__main__.__builtins__.__dict__):
print bis
}}}
In action:
{{{
# These are being entered in the Python shell, which is
# the __main__ scope:
import scopeTest
# just a test var
var = 23
}}}
{{{
scopeTest.scopeTestMain()
# prints:
__builtins__
__doc__
__file__
__name__
scopeTest
var
}}}
A brief tangent: Executing this in the same Python shell will print the same data, since {{{dir()}}} without any arguments will return the list of names in the current local scope... which in this case is the {{{__main__}}} scope (since it's in the Python shell):
{{{
for d in sorted(dir()):
print d
# prints:
__builtins__
__doc__
__file__
__name__
scopeTest
var
}}}
Continuing test...
{{{
scopeTest.scopeTestBuiltin()
# prints:
ArithmeticError
AssertionError
AttributeError
BaseException
# ... a whole lotta other stuff...
type
unichr
unicode
vars
xrange
zip
}}}
{{{
scopeTest.scopeTestBuiltins()
# prints:
ArithmeticError
AssertionError
AttributeError
BaseException
# ... a whole lotta other stuff...
type
unichr
unicode
vars
xrange
zip
}}}
----
Things of note:
*{{{__main__}}} collectes all our 'most globalist' (I made up that word) variables: 'local' vars refer to variables inside functions. 'global' variables refer to variables in the top level of a module. I tend to call {{{__main__}}} the 'universal' scope. Note (below) the variables collected there in our above example. This is because they were either imported into, or declared at, the 'top most' {{{__main__}}} scope.
**{{{scopeTest}}}
**{{{var}}}
*{{{__builtin__}}} and {{{__builtins__}}} both have the exact same data in them.
*If you run {{{type()}}} on {{{__main__}}}, {{{__builtin__}}}, and {{{__builtins__}}}, Python say they are all {{{<type 'module'>}}}.
''Note'': I wrote the below section before I really grasped the difference in concept between 'parameters' and 'arguments'. So //everything// I discuss below this note is refers to 'arguments only'. However, parameters and arguments are two different things, which I'll describe here first, and maybe get around to re-authoring the below text later ;)
A function can take a series of identifiers, also known as //parameters//:
{{{
def foo(parameter1, parameter2="defaultArgument"):
# do work
}}}
And when you call to the function you pass values, known as //arguments//, to the parameters:
{{{
foo('argument1')
}}}
Based on this example, the //parameter// {{{parameter2}}} has a //[[default argument|Default Arguments]]// with the string //value// of {{{"defaultArgument"}}}. If you don't pass an argument to {{{parameter2}}} when the function is called, then the //default argument// is used instead. The //parameter// {{{paramter1}}} has the argument {{{'argument1'}}} passed in.
So when 'parameters' are discussed, they refer to the 'identifier name' the function expects, and when 'arguments' are discussed, it refers to the 'values' passed into the function.
----
----
[[Function]] @@//definitions//@@ can take arguments. This allows data to be passed into them, that would otherwise be external to their universe.
There are four different ways of assigning arguments to a function definition, and they need to be arranged in a specific order:
*{{{arg}}} : The function matches normal arguments by //position//, left to right, when passed in.
<<<
{{{
def foo(argA, argB):
print argA, argB
foo("b", "a")
# b a
}}}
<<<
*{{{arg = value}}} : The function has a //default value// assigned to the keyword. But the user can override this with their own value.
<<<
{{{
def foo(argA = "", argB = "23", argC = "happy"):
print argA, argB, argC
foo(argB="b", argA="a")
# a b happy
}}}
<<<
*{{{*args}}} : Collects any number of unmatched //positional// arguments into a new {{{tupple}}} for processing. The variable name is arbitrary, it just needs to be preceded with a single asterix '{{{*}}}'.
<<<
{{{
def foo(*args):
print "made a tupple: ", args
for a in args:
print a, "!!!"
foo("A", "B", "C")
# made a tupple: ("A", "B", "C")
# A !!!
# B !!!
# C !!!
}}}
<<<
*{{{**kwargs}}} : Collects any number of unmatched //keyword// arguments into a new {{{dictionary}}} for processing. The variable name is arbitrary, it just needs to be preceded with double asterix '{{{**}}}'.
<<<
{{{
def foo(**kwargs):
print "made a dictionary: ", kwargs
for key in kwargs:
print key + " : " + kwargs[key]
foo(keyA="valA", keyB="valB", keyC="valC")
# made a dictionary: {'keyC': 'valC', 'keyB': 'valB', 'keyA': 'valA'}
# keyC : valC
# keyB : valB
# keyA : valA
}}}
<<<
An example function using all four methods, listing them in the correct order:
{{{
def argTest(positional, defaultValue="notArg1", *args, **kwargs):
print "positional1:", positional
print "defaultValue:", defaultValue
print "*args:", args
print "**kwargs:", kwargs
argTest("ARG1",
"replaced default val",
"unmatched positional A", "unmatched positional B",
keywordA="A",
keywordB="B")
}}}
prints:
{{{
positional1: ARG1
defaultValue: replaced default val
*args: ('unmatched positional A', 'unmatched positional B')
**kwargs: {'keywordB': 'B', 'keywordA': 'A'}
}}}
You can have as many '//positional//' {{{arg}}}'s as you want, as long as they exist before any 'keyword/default value' args ({{{arg = value}}}). You can have as many 'keyword/default value' args as you want, as long as they're listed before {{{*args}}} and {{{**kwargs}}}. There is only a single call to both {{{*args}}} and {{{*kwargs}}}.
----
When @@//calling//@@ to a defined function with arguments, similar rules apply:
*Normal arguments are matched by //position//.
<<<
{{{
def foo(argA, argB):
print argA, argB
foo("b", "a")
# b a
}}}
<<<
*Keyword variables that have default values can be entered in any order, or not at all:
<<<
{{{
def foo(argA = "", argB = "", argC = "C!!!"):
print argA, argB, argC
foo(argB="b", argA="a")
# a b C!!!
}}}
<<<
*You can pass all objects in a list\tupple as individual positional arguments, by prefixing the variable name with an asterix '{{{*}}}'. The function will unpack the list\tupple. This is sort of the inverse of function argument //assignment// {{{*args}}} (above). It's important that the list\tupple has the same number of items as the function has expectant arguments, or an exception will be raised.
<<<
{{{
def foo(argA, argB, argC, argD):
print argA, argB, argC, argD
args = ("a", "b", "c", "d")
foo(*args)
# a b c d
}}}
<<<
*You can pass all the key\value pairs from a dictionary via the double-asterix '{{{**}}}'. The function will unpack the dictionary. This is similar to the inverse of function argument //assignment// {{{**kwargs}}} (above). It's important that the dictionary has the same number\names of keys as the function has arguments, or an exception will be raised.
<<<
{{{
def foo(argA, argB, argC, argD):
print argA, argB, argC, argD
kwargs = {"argA":1, "argB":2, "argC":3, "argD":4}
foo(**kwargs)
# 1 2 3 4
}}}
<<<
----
Additional Info:
*Arguments are passed by 'automatically assigning objects' to local names.
**In the above //definition// example, {{{argA}}} is in the local scope of {{{def foo()}}}
*Assigning to immutable argument names inside a function doesn't affect the caller.
**If in {{{foo()}}} you decide to set {{{argA}}} to {{{42}}}, that won't effect the caller that passed in the object, since the integer 42 is immutable. See next:
*''Immutable'' arguments are passed in 'by value'.
**Which in effect is like passing in a duplicate copy, since they //can't// be changed in-place.
*''Mutable'' objects are passed in 'by reference'.
*Changing a mutable object argument //in// a function may impact the caller. An example of this would be passing in a list: Changing the list in the function can effect the list outside the function, since lists are mutable.
**Meaning, if you change a passed in mutable object in the function, it //can and will// modify that object in place.
**Mutable arguments are passed in 'by pointer'. As above: The function that is receiving them has a pointer to the original object, so it can be changed in-place by the function.
Example of the last three bullets:
{{{
l = ["a", "s", "d", "f"] # mutable list (that's a lower-case 'L', fyi)
n = 42 # immutable integer
def foo(lister, number):
lister.append("snuff") # change in-place via object method
number = 23 # define new local variable.
print l
# ['a', 's', 'd', 'f']
print n
# 42
foo(l,n)
print l
# ['a', 's', 'd', 'f', 'snuff']
print n
# 42
}}}
{{{l}}} is a mutable sequence, so the function //did// change its value. But the number {{{n}}} is immutable, so no change happened.
----
Also see:
*[[Default Arguments]]
*Another [[blog post|http://www.saltycrane.com/blog/2008/01/how-to-use-args-and-kwargs-in-python/]] describing {{{*args}}} and {{{**kwargs}}}.
I keep forgetting this simple syntax... so I write it down:
{{{
>>> assert 1==2, "Sorry, those don't equal"
AssertionError: Sorry, those don't equal
}}}
If the {{{assert}}} fails, it raises an {{{AssertionError}}}
The term attribute in Python has several meanings, as I'm coming to learn. Attributes are tied very closly to [[namespace]]s, so be sure to see the notes on that.
Also see [[Special Attributes]]
----
''Importing Attributes''
When you [[import]] one module into another, that module is imported into a [[namespace]]. The functions, variables, and classes defined in that module (basically, all the names declared at the //top level// of a module) become accessible as attributes by the importing module via the [[namespace]]'s 'dot notation': '{{{namespace dot attribute}}}'
{{{
# myFile.py
def myFunc():
return 23
someVal = "spam!"
}}}
{{{
# myOtherFile.py
# Imported the variables and functions from myFile
# into a namespace 'myFile':
import myFile
# Access via 'dot notation':
print myFile.someVal
print myFile.myFunc()
}}}
Then, when executing {{{myOtherFile.py}}}
{{{
spam!
23
}}}
{{{myOtherFile.py}}} could also be authored like this:
{{{
from myFile import someVal
print someVal
}}}
This imports someVal directly into the namespace of {{{myOtherFile}}}, so the variable no longer has to be access via dot notation. See notes on [[import]].
----
There are a variety of ways to access attributes. In the below example I use a string variable, but it could just as easily be a [[module]] or [[Class]]
{{{
# module.py
value = "spam!"
}}}
{{{
import sys
import module
foo = module.value
foo = module.__dict__['value']
foo = sys.modules['module'].value
foo = getattr(module, 'value')
# all return the same value to foo: "spam!"
}}}
From above
*{{{module.value}}} : The most common way of accessing the attribute (IMO).
*{{{module.__dict__['value']}}} : Acces the module object's {{{__dict__}}} attribute, and query the current value of variable {{{value}}}.
*{{{sys.modules['module'].value}}} : {{{sys.modules}}} is a dictionary of the loaded modules. Via this example, we query the value of attribute {{{.value}}} on object {{{module}}} by looking into that dictionary.
*{{{getattr(module, 'value')}}} : Use the built-in function to pull the value.
Furthermore, you can add arbitrary attributes to objects as well:
{{{
module.attr = "attribute!"
print module.attr
# attribute!
}}}
----
''Attributes in Classes''
Attributes can be variables that are associated with an object, as instanced via a [[Class]]. (Also see [[Class - advanced]] & [[Class Attributes]])
Attributes are accessed via 'dot notation'.
Simple example:
{{{
class Foo(object):
def __init__(self, namer, num):
self.name = namer # make an attr called .name
self.__number = num # make an private class-attr called .__number.
# continue...
}}}
Once you make an object, any non-private attrs you can access:
{{{
f = Foo("bob", 3)
print f.name
# "bob"
}}}
You can still access the private attr, but you //shouldn't//, since it //is private//, and probably very shy.
----
From the [[PEP8 style guide|http://www.python.org/dev/peps/pep-0008/]]:
*{{{__double_leading_and_trailing_underscore__}}}: "magic" objects or attributes that live in user-controlled namespaces. E.g. {{{__init__}}}, {{{__import__}}} or {{{__file__}}}. Never invent such names; only use them as documented.
*{{{__double_leading_underscore}}}: when naming a class attribute, invokes name mangling (inside {{{class FooBar}}}, {{{__boo}}} becomes {{{_FooBar__boo}}}). -- This means it's a //private attribute//
*Use one leading underscore only for non-public methods and instance variables (see notes on [[import]]).
Python 3 switched many return values from a {{{str}}} to {{{bytes}}}.
Python 3 docs for [[str|https://docs.python.org/3/library/stdtypes.html#text-sequence-type-str]]
From the Python3 [[bytes docs|https://docs.python.org/3/library/stdtypes.html#bytes-objects]]:
<<<
Bytes objects are immutable sequences of single bytes. Since many major binary protocols are based on the ASCII text encoding, bytes objects offer several methods that are only valid when working with ASCII compatible data and are closely related to string objects in a variety of other ways.
<<<
So rather than this:
{{{
ms = "my string"
}}}
You'd see:
{{{
mbs = b"my string"
}}}
However, some calls still want strings, not bytes. How do you convert between them?
You'd think this would work:
{{{
converted = str(mbs)
}}}
but in fact, it leaves it as bytes.
As it turns out, you need to //decode// the bytes, so it knows what 'type' of string to turn into, and there are 'many types'.
However, {{{utf-8}}} is the default, so you can omit it from the method if you want:
{{{
converted = mbs.decode()
print(mbs)
print(converted)
b'my string'
my string
}}}
You can also convert a string to bytes via it's {{{encode}}} method. {{{utf-8}}} is the default, so you can omit that from the method.
{{{
mystr = "a string"
myBytes = mystr.encode()
print(myBytes)
b'a string'
}}}
----
Also see:
* https://docs.python.org/3/library/codecs.html#standard-encodings
* https://docs.python.org/3/howto/unicode.html
** ''~UTF-8'' is one of the most commonly used encodings, and Python often defaults to using it. UTF stands for “Unicode Transformation Format”, and the ‘8’ means that 8-bit values are used in the encoding.
* https://home.unicode.org/
* https://en.wikipedia.org/wiki/Character_encoding
https://docs.python.org/2/library/csv.html
----
{{{
# Write to CSV file:
import csv
path = "c:/temp/some.csv"
myStuff = [["1A", "2A", "3A"],
["1B", "2B", "3B"]]
with open(path, 'wb') as csvfile:
csvWriter = csv.writer(csvfile, delimiter=',')
csvWriter.writerow(["Header A", "Header B", "Header C"])
for listOfData in myStuff:
csvWriter.writerow([listOfData[0], listOfData[1], listOfData[2]])
}}}
looks like this in Notepad:
{{{
Header A,Header B,Header C
1A,2A,3A
1B,2B,3B
}}}
----
{{{
# Read from CSV file:
import csv
path = "c:/temp/some.csv"
with open(path, 'rb') as csvfile:
csvReader = csv.reader(csvfile, delimiter=',')
for row in csvReader:
print row
}}}
{{{
['Header A', 'Header B', 'Header C']
['1A', '2A', '3A']
['1B', '2B', '3B']
}}}
>Docs on [[ctype array creation|http://docs.python.org/library/ctypes.html#arrays]], which showcase much more compactly what I'm describing below (found these docs after I authored the below stuff...)
I'm not even sure the title accurately explains what I'm trying to... explain... :) I currently only have the most rudimentary conceptualization behind how [[ctypes|http://docs.python.org/library/ctypes.html]] work, but while working in [[pyglet|http://www.pyglet.org]] the other day I saw this line of code (from page 14 of the [[programming_guide.pdf|http://www.pyglet.org/doc/programming_guide.pdf]])
{{{
vertices_gl = (GLfloat * len(vertices))(*vertices)
}}}
Initially, it looked like it was multiplying one tuple {{{(GLfloat * len(vertices))}}} by another {{{(*vertices)}}}. But this didn't seem right. Since {{{GLfloat}}} was from the {{{pyglet}}} GL lib, I wanted to recreate this using something builtin, so I did with {{{ctypes.c_double}}}.
Example below is a modified version from the programming guide with that change:
{{{
import ctypes
vertices = [0,0, 0,1, 1,1, 1,0]
vertices_gl = (ctypes.c_double * len(vertices))(*vertices)
print vertices_gl
}}}
{{{
<__main__.c_double_Array_8 object at 0x00000000028FA9C8>
}}}
So the end result is a {{{c_double_Array_8}}} //object//. And the '8' will change dynamically based on how many items are put in the {{{vertices}}} list.
But this still didn't help my understanding much, so I broke it down a bit more:
{{{
import ctypes
vertices = [0,0, 0,1, 1,1, 1,0]
cDoubleArray = (ctypes.c_double * len(vertices))
print cDoubleArray
vertices_gl = cDoubleArray(*vertices)
print vertices_gl
}}}
{{{
<class '__main__.c_double_Array_8'>
<__main__.c_double_Array_8 object at 0x00000000028FAEC8>
}}}
*That makes a bit more sense: {{{cDoubleArray = (ctypes.c_double * len(vertices))}}} returns a dynamically created {{{c_double_Array_8}}} ''//class//''. Meaning, the type of class (the {{{_8}}} part) will change based on how many items are in the {{{vertices}}} list. Didn't know you could do that.
*When you put parenthesis immediately after it, you're calling to the class to create an ''//object//'': {{{vertices_gl = cDoubleArray(*vertices)}}}
*And by putting the asterisk in front of the argument {{{cDoubleArray(*vertices)}}}, you directly unpack the {{{vertices}}} variable into the expectant positional args of the class's {{{__init__}}} func. Meaning, rather than passing in a list of eight items, you directly pass in eight items.
So in a nutshell the below line:
{{{
vertices_gl = (GLfloat * len(vertices))(*vertices)
}}}
Is dynamically creating a ctypes 'double array' class, and instancing an object from it in one line.
decimal is a module that can be imported to deal with (among other things) floating point precision issues.
In the below example, we multiply a number by 2. The result seems to be ok, but behind the scenes actually, it's slightly off:
{{{
import decimal
num = 3.1415 * 2
print num
>>> 6.283 # is this really true?
print num.__repr__()
>>> 6.2830000000000004 # sigh, floating point badness
# note, you need to turn it into a string first:
d = decimal.Decimal(str(num))
print d
print d.__repr__()
>>> 6.283
>>> Decimal('6.283')
}}}
But turning this back into a float seems to bring back the problems again :(
{{{
num = float(d)
print num.__repr__()
>>> 6.2830000000000004
}}}
Official docs:
http://docs.python.org/glossary.html#term-decorator
http://docs.python.org/reference/compound_stmts.html#function
Some documentation
*[[Python Decorators|http://pythonconquerstheuniverse.wordpress.com/2012/04/29/python-decorators/]] : Probably the best one I've found.
*[[Decorators I: Introduction to Python Decorators|http://www.artima.com/weblogs/viewpost.jsp?thread=240808]]
*[[Decorators II: Decorator Arguments|http://www.artima.com/weblogs/viewpost.jsp?thread=240845]]
*[[Python Decorators Don't Have to be (that) Scary|http://www.siafoo.net/article/68]]
*[[Python Decorator Library|http://wiki.python.org/moin/PythonDecoratorLibrary]]
See a simple example here: [[How can I write a program timer?]]
Decorators simply wrap one function in another with the syntax '{{{@wrapperFunction}}}'. From the above docs:
{{{
# implementation A (python 2.4 and earlier):
def f(...):
...
f = staticmethod(f)
}}}
{{{
# implementation B (decorator implementation):
@staticmethod
def f(...):
...
}}}
Both have the same result. The {{{staticmethod()}}} function obviously does something important, and it wrappers another function {{{f()}}} to pull off its results. But as you can see, there are are two different ways to implement this functionality:
In the first (A), you create your arbitrary function {{{f()}}}, then pass {{{f}}} directly into the {{{staticmethod()}}} function returning an 'updated' version of {{{f}}}.
In the second (B), you physically use the 'at sign' //decorator// {{{@}}} in front of your wrapper function, and place it on the line above the function to be decorated.
----
Common uses for decorators include the functions [[property]], [[classmethod|Class Methods]], [[staticmethod|Static Methods]], ...?
----
Simple example, allowing us to wrapper a class method, showing how to execute code before and after the class method executes:
{{{
def myDecorator(f):
def wrapper(*args, **kwargs):
print "Before"
result = f(*args, **kwargs)
print "After"
return result
return wrapper
class Spam(object):
@myDecorator
def eggs(self, salt, pepper=23):
print "eggies!", salt, pepper
}}}
{{{
s = Spam()
s.eggs("salty", pepper=42)
}}}
{{{
Before
eggies! salty 42
After
}}}
----
You can also do this with a class, but it only works on functions, not class methods:
{{{
class MyDecorator(object):
def __init__(self, f):
self.f = f
def __call__(self, *args, **kwargs):
print "Before"
self.f(*args, **kwargs)
print "After"
@MyDecorator
def eggs(salt, pepper=23):
print "eggies!", salt, pepper
}}}
{{{
eggs("salty", pepper=42)
Before
eggies! salty 42
After
}}}
{{{import}}} is a statement ([[python docs|http://docs.python.org/ref/import.html]]).
Also see the built-in {{{__import__}}} //function//, which the {{{import}}} //statement// actually runs. - [[Python Docs|http://docs.python.org/lib/built-in-funcs.html]]
[[Modules|module]] need to be //imported// before they can be used in another module:
{{{
# moduleA.py
def adder(x, y):
return x + y
def foo():
print "foo!"
}}}
Importing {{{moduleA.py}}} into {{{moduleB.py}}} puts an //instance// (rather than a copy, see notes below) of {{{moduleA.py}}} into the {{{moduleA}}} [[namespace]] by default (see notes on [[__name__]]):
{{{
# moduleB.py
import moduleA
num = moduleA.adder(2,2)
print num
# 4
}}}
You can also use the {{{from}}} statement to extract certain [[attribute]]s (functions, classes, variables) from a module. These attributes are //copied// (rather than instanced, see notes below) directly to the current namespace, stomping the values of any previously named variables (this is usually bad, so use with care). In the below example, since {{{adder()}}} //isn't// imported, it //can'//t be executed.
{{{
# moduleC.py
from moduleA import foo
foo()
# foo!
num = adder(2,3)
# Traceback (most recent call last):
# File "<string>", line 1, in <string>
#NameError: name 'adder' is not defined
}}}
You can also use '{{{as}}}' in the {{{import}}} line to control the [[namespace]] the module is added to:
{{{
# import just moduleA.adder() into "a"
from moduleA import adder as a
num = a(4,4)
# import all of moduleA into namespace "a"
import moduleA as a
num = a.(4,4)
a.foo()
}}}
Finally, you can {{{import}}} 'everything' via the asterix '{{{*}}}' notation. This means you can now access the [[attribute]]s without having to use dot notation (name dot attribute). It should be noted that for the most part, this is [[frowned upon|http://docs.python.org/howto/doanddont.html#from-module-import]].
{{{
from moduleA import *
num = adder(4,6)
print num
foo()
# 10
# foo!
}}}
As with the '{{{from module import attribute}}}' example (above), there is a danger with this: It will stomp any pre-existing variable names with the new defintions. Presume you had defined a function called {{{sys}}} in {{{moduleA.py}}}, then executed the above example. The built-in {{{sys}}} command would no longer work within the current module (probably not the effect one is after). However, I'm told some libraries\modules //are// acceptable to import this way, notably the built-in {{{Tkinter}}}.
----
''Differences in importing:''
Compare these two import statements (and additional equivalent statements sub-listed under them):
#{{{import someModule}}}
##{{{import someModule as sm}}}
#{{{from someModule import *}}}
##{{{from someModule import someAttr}}}
##{{{from someModule import someAttr as someName}}}
In the first example, one instance of {{{someModule}}} is shared (instanced) among every other module that imports it (in that fashion). Any change you make in it or to it will appear in all modules importing it.
In the second example, a //copy// of the module is brought into the current scope. Change made in the source {{{someModule}}} won't be be seen by other modules. Basically, if you have {{{from}}} in the import statement, you're making a copy of the data.
Example: Make the following modules:
{{{testGlobals.py}}} holds a few attributes that we can later change:
{{{
# testGlobals.py
foo = "foo"
spam = "spam"
}}}
{{{updateGlobals.py}}} imports (instances) testGlobals, and modifies its attributes (modifies the values in the source module).
{{{
# updateGlobals.py
import testGlobals
def update():
testGlobals.foo = "new FOO"
testGlobals.spam = "new SPAM"
}}}
{{{module_importInstance.py}}} imports an instance of {{{testGlobals.py}}} into its namespace, keeping a "live connection" to any changes that happen to the source module.
{{{
# module_importInstance.py
import testGlobals
import updateGlobals
print "Imported foo and spam values:"
print testGlobals.foo
print testGlobals.spam
updateGlobals.update()
print "foo and spam after source module update:"
print testGlobals.foo
print testGlobals.spam
}}}
{{{module_importCopy.py}}} //copies// the data from {{{testGlobals.py}}} into its namespace. It no longer has any connection to the source module.
{{{
# module_importCopy.py
from testGlobals import *
import updateGlobals
print "Imported foo and spam values:"
print foo
print spam
updateGlobals.update()
print "foo and spam after source module update:"
print foo
print spam
}}}
Now, to see them in action, execute from the command prompt (Windows example):
{{{
c:\myPython\module_importInstance.py
Imported foo and spam values:
foo
spam
foo and spam after source module update:
new FOO
new SPAM
}}}
Above, you can see that the change made to the source {{{testGlobals.py}}} DID have a result in our module.
Next up...:
{{{
c:\myPython\module_importCopy.py
foo
spam
foo and spam after source module update:
foo
spam
}}}
Notice now that modifying the source module's values had no effect here, since a //copy// of that data was imported.
----
''Relative Imports''
If you have a [[package|Packages]] setup, you can do relative imports. Here are [[docs|http://docs.python.org/tutorial/modules.html#intra-package-references]]
{{{
# myModule.py
# These two are the same:
import someModule
from . import someModule
# This looks a dir up:
from .. import someOtherModule
}}}
The above examples we're looking in directories relative to {{{myModule.py}}}.
'single dot' says look in the current dir, 'double-dot' says look a dir up, etc.
----
''Private attributes and importing:''
There are two ways to limit how things are imported from a module, based on the '{{{from module import *}}}' statement:
#Prefixing names with a single underscore '{{{_}}}' will prevent that data being copied out
#Create a list variable called {{{__all__}}} with the names (as strings) of the attributes that //are// acceptable to be copied out. This is sort of the opposite of the previous solution.
{{{
# secret.py
__all__ = ["notSecretVar"]
_secretVar = "secret!"
def _secretFunc():
print "very secret!"
notSecretVar = "not so secret"
def notSecretFunc():
print "not secret at all"
}}}
Execution:
{{{
from secret import *
print notSecretVar
# not so secret
notSecretFunc()
# Traceback (most recent call last):
# File "<string>", line 1, in <string>
# NameError: name 'notSecretFunc' is not defined
print _secretVar
#Traceback (most recent call last):
# File "<string>", line 1, in <string>
#NameError: name '_secretVar' is not defined
_secretFunc()
# Traceback (most recent call last):
# File "<string>", line 1, in <string>
# NameError: name '_secretFunc' is not defined
}}}
None of the [[attribute]]s that had leading underscores were copied with the '{{{from module import *}}}' statement, so trying to execute them failed.
Furthermore, even though the function {{{notSecretFunc()}}} has no leading underscore, it //wasn't// added to the '{{{__all__}}}' list, so it wasn't exported out either.
Realize that these rules //only// matters when using the {{{from module import *}}} statement. Doing a regular {{{import secret}}} //would// expose all of our 'secret' attributes.
----
When importing a module, Python has to go find it first. This is the order it uses for the search:
#Home dir of the program (the location of the top-level module that was executed).
#{{{PYTHONPATH}}} dirs, if any are set.
#The Standard Library dirs: {{{<drive>:\Python<ver>\Lib\*}}}
#Dirs defined by any {{{.pth}}} files (if they exist).
The result of these four become what {{{sys.path}}} returns.
----
Concepts:
*When imported, modules live in a [[namespace]].
*All of the names declared at the //top level// of a module become [[attribute]]s of the imported 'module object'.
*Importing gives access to names ([[attribute]]s) defined in the module's global [[scope|Python variable scope]]
Iteration is a common thing to do in Python: A bunch of stuff, loop (iterate) over it. The {{{for}}} statement is one of the most common ways to iterate over something: Those objects know how how to respond to the {{{for}}} statement and iterate accordingly.
Python has a variety of different ways to do this based on different data types:
''File Objects'':
Iterating in a for loop:
{{{
for line in open('myfile.txt'):
print line
# the above example is better than the next (older) example,
# because it's easier to code, easier to run, and uses less memory:
for line in open('myfile.txt').readlines():
print line
}}}
Using the file object's {{{.readline()}}} method:
{{{
f = open('myfile.txt')
print f.readline()
# line one
print f.readline()
# line two
f.close()
}}}
Same as above, but using the {{{.next()}}} method, which will raise a built-in {{{StopIteration}}} when the end is reached:
{{{
f = open('myfile.txt')
print f.next()
# line one
print f.next()
# line two
f.close()
}}}
''Lists'':
{{{
lister = ["a", "b", "c"]
it = iter(lister)
print it.next()
# a
}}}
The {{{iter}}} function will raise a {{{StopIteration}}} exception when it reaches the end of the list. This is //awfully// similar to [[generator functions|Function]].
''Dictionary'':
The 'older' method of looping through 'key:value' pairs was to do this:
{{{
D = {"key1":"value1", "key2":"value2"}
for key in D.keys():
print key, D[key]
}}}
But more recent version of Python no longer require you to call the {{{.keys()}}} method, dictionaries now have a built-in iterator to do this for you:
{{{
D = {"key1":"value1", "key2":"value2"}
for key in D:
print D, D[key]
}}}
''List Comprehensions'':
{{{
# strip off all the return chars in a file, and put into a list,
# while iterating over a file:
clean = [line.rstrip() for line in open('myfile.txt')]
}}}
''OOP''
When creating your //own// objects via a Class, you can define a special {{{__iter__}}} method to support iteration. Meaning, when you call:
{{{
for thing in myObjectList:
# doStuff...
}}}
it'll look to that objects {{{__iter__}}} method for what exactly should be happening...
In addition to sequence operations and list methods, you can //really// try and confuse yourself with list comprehensions ;) It is said they can run up to twice as fast as a 'for loop'... so if speed is your thing, check them out...
List comprehensions take lists, and create new lists from them. They are enclosed in square brackets: {{{[]}}}
Python docs:
http://docs.python.org/tutorial/datastructures.html#list-comprehensions
(See notes on ''generator expressions'' at the bottom)
----
Given two list of numbers (of the same length, in this case they're vectors), add each index from each list toether:
{{{
vec1 = [1,0,0]
vec2 = [0,1,0]
sum = [vec1[i] + vec2[i] for i in range(len(vec1))]
# [1, 1, 0]
}}}
----
Some examples: (I pulled a bunch of notes from 'Learning Python Third Edition by Mark Lutz')
{{{
# make a 3x3 matrix :
mx = [[1,2,3], [4,5,6], [7,8,9]]
# get just the middle column from the matrix:
col2 = [row[1] for row in mx]
print col2
>>> [2, 5, 8]
}}}
{{{
# add a value to the middle column (but don't actually modify the matrix)
print [row[1] + 1 for row in mx]
>>> [3, 6, 9]
}}}
{{{
# get only even numbers from the middle column:
print [row[1] for row in mx if row[1] % 2 == 0]
>>> [2, 8]
}}}
{{{
# pull diagonal values:
diagonal = [mx[i][i] for i in [0,1,2]]
print diagonal
>>> [1, 5, 9]
}}}
{{{
# Repeat chars in a string
word = "foo"
double = [i * 2 for i in word]
print double
>>> ['ff', 'oo', 'oo']
}}}
{{{
# Comparing list comprehensions, and for loops:
# List Comprehension:
squares = [i ** 2 for i in range(1,6)]
print squares
>>> [1, 4, 9, 16, 25]
# For Loop equivalent:
squares = []
for i in range(1,6):
squares.append(i**2)
print squares
>>> [1, 4, 9, 16, 25]
}}}
----
Turn multiple lists into a single list, presuming all the lists are the same size:
{{{
A = [1, 4, 7, 10]
B = [2, 5, 8, 11]
C = [3, 6, 9, 12]
Z = [item[i] for item in zip(A, B, C) for i in range(3)]
print Z
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
}}}
----
Turn a list into a grouping of sublists.
Here, we take a list of 16 items (from a matrix), and turn it into a list with four sub-lists, each with four items.
(Pulled from [[this post|http://www.garyrobinson.net/2008/04/splitting-a-pyt.html]])
{{{
mtxList = [1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0]
size=4
mtxQuad = [mtxLst[i:i+size] for i in range(0, len(mtxLst), size)]
print mtxQuad
# [[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0]]
}}}
----
{{{
# return number, and cube root of number 1-5:
cubeRoots = [[x, x ** 3] for x in range(1,6)]
print cubeRoots
>>> [[1, 1], [2, 8], [3, 27], [4, 64], [5, 125]]
}}}
----
More examples I pulled directly from the [[Python reference|http://docs.python.org/tut/node7.html#SECTION007140000000000000000]]:
As you can see, you can also inlude {{{if}}} clauses in the list comprehension for testing:
{{{
# strip whitespace:
freshfruit = [' banana', ' loganberry ', 'passion fruit ']
print [weapon.strip() for weapon in freshfruit]
>>> ['banana', 'loganberry', 'passion fruit']
}}}
{{{
vec = [2, 4, 6]
print [3*x for x in vec]
>>> [6, 12, 18]
print [3*x for x in vec if x > 3]
>>> [12, 18]
print [3*x for x in vec if x < 2]
>>> []
print [[x,x**2] for x in vec]
>>> [[2, 4], [4, 16], [6, 36]]
print [(x, x**2) for x in vec]
>>> [(2, 4), (4, 16), (6, 36)]
vec1 = [2, 4, 6]
vec2 = [4, 3, -9]
print [x*y for x in vec1 for y in vec2]
>>> [8, 6, -18, 16, 12, -36, 24, 18, -54]
print [x+y for x in vec1 for y in vec2]
>>> [6, 5, -7, 8, 7, -5, 10, 9, -3]
print [vec1[i]*vec2[i] for i in range(len(vec1))]
>>> [8, 12, -54]
}}}
----
Working on multiple lists at once:
{{{
A = ['a0', 'a1']
B = ['b0', 'b1']
C = ['c0', 'c1']
D = [(a,b,c) for a in A for b in B for c in C ]
for d in D:
print d
}}}
prints:
{{{
('a0', 'b0', 'c0')
('a0', 'b0', 'c1')
('a0', 'b1', 'c0')
('a0', 'b1', 'c1')
('a1', 'b0', 'c0')
('a1', 'b0', 'c1')
('a1', 'b1', 'c0')
('a1', 'b1', 'c1')
}}}
----
While there doesn't seem to be such thing as a '{{{tuple comprehension}}}', you can turn any list comprehension into a {{{tuple}}}:
{{{
foo = tuple([3*x for x in vec])
# (6, 12, 18)
}}}
I've seen examples of this:
{{{
foo = tuple(3*x for x in vec)
# (6, 12, 18)
}}}
Which creates a //generator expressions// (see below), and turns that into a {{{tuple}}}, but I've read it's actually slower that way.
----
You can also do a mashup of list comprehensions and [[generator functions|Function]] to make '''generator expressions'''. They act like list comprehensions, but are surrounded in parenthesis instead of square brackets.
{{{
genEx = (x * 2 for x in ["a", "b", "c"])
print genEx.next()
# aa
print genEx.next()
# bb
# etc...
}}}
They raise a {{{StopIteration}}} exception when complete.
I read that generator expressions are known to save on memory, since they don't require the entire list to be constructed at once, but can actually run slower in practice, so should really only be used on large data sets.
See the [[generator function|Function]] notes for more info on their methods.
http://matplotlib.sourceforge.net/
*"matplotlib is a python 2D plotting library which produces publication quality figures in a variety of hardcopy formats and interactive environments across platforms. matplotlib can be used in python scripts, the python and ipython shell (ala matlab or mathematica), web application servers, and six graphical user interface toolkits.
matplotlib tries to make easy things easy and hard things possible. You can generate plots, histograms, power spectra, bar charts, errorcharts, scatterplots, etc, with just a few lines of code."
A ''text file'' containing one or more Python [[Statement]]s and/or definitions (of [[Function]]s, [[Class]]es & variables). Most modules also contain comments. They are the 'highest level' organization unit in Python.
Modules are //processed// with two [[Statement]]s, and a built-in function:
*{{{import}}} - [[Python Docs|http://docs.python.org/ref/import.html]].
**Also see the built-in {{{__import__}}} function, which the {{{import}}} statement actually runs. - [[Python Docs|http://docs.python.org/lib/built-in-funcs.html]]
*{{{from}}} - (same docs as above)
*{{{reload}}} - [[Python Docs|http://docs.python.org/lib/built-in-funcs.html]]
There are (at least) three kinds of modlues in Python:
*modules written in Python (.py) [[Global Module Index|http://docs.python.org/modindex.html]]
*modules written in C and dynamically loaded (.dll, .pyd, .so, .sl, etc)
*modules written in C and linked with the interpreter; to get a list of these, type:
<<<
{{{
import sys
print sys.builtin_module_names
}}}
<<<
Modules need to be [[import]]ed before they can be used in another module.
Once a module is [[import]]ed, you can use this to see a list of its [[attribute]]s:
{{{
dir(modulename)
}}}
Also after import, a special attribute '{{{.__name__}}}' is set on the module: {{{__name__}}} holds the value of the current [[namespace]] that the object lives in. If the module is the 'top level' being executed (meaning, it //hasn't// been imported, it's being directly executed) '{{{.__name__}}}' becomes the string {{{"__main__"}}}. If the module has been imported, then '{{{.__name__}}}' is assigned to the [[namespace]] that the module was imported in to. Check out '[[What's up with: if __name__ == "__main__":]]' for more on this.
Concepts:
*When imported, modules live in a [[namespace]].
*All of the names declared at the //top level// of a module become [[attribute]]s of the imported 'module object'.
*Importing gives access to names ([[attribute]]s) defined in the module's global [[scope|Python variable scope]]
----
''Special Module Attributes'':
*{{{__name__}}} is the module’s name
*{{{__doc__}}} is the module’s documentation string, or None if unavailable
*{{{__file__}}} is the pathname of the file from which the module was loaded, if it was loaded from a file. Could be absolute or relative.
----
General module contents:
{{{
"""module docstring"""
# imports
# constants
# exception classes
# interface functions
# classes
# internal functions & classes
def main(...):
...
if __name__ == '__main__':
status = main()
sys.exit(status)
}}}
----
Also see:
*[[Python File Formats]]
Namespaces are a fairly important concept to understand in Python. Where to begin...
*Most commonly you author Python code that is saved in a module. That module is in a namespace, which is normally the module name. If you import //other// modules into it, each of the new modules exist in their own namespaces, defined by their own names (this can be changed though via the {{{import}}} command, more on this below). Data in namespaces is accessed via 'dot notation', which basically is:
{{{
namespace dot attribute
}}}
*Which brings up the question, what is an [[attribute]]? When you assign (bind) data (variables, functions, classes, etc) to a name (like {{{foo = 23}}}), that data becomes an //attribute// of the //module// it was authored in. So that attribute now lives in the //namespace// of its parental module:
{{{
# someModule.py
# Create a variable called foo.
# It is now an attribute of someModule.py,
# And lives in someModule's namespace.
foo = 23
}}}
**Inside of {{{someModule.py}}}, you can simply reference the attribute by name ({{{foo}}}) throughout it, since the parental namespace is assumed and need not be provided. If {{{someModule.py}}} was imported into //another// module (thus placing it in the {{{someModule}}} namespace by default), you would need to reference the attribute via 'dot notation'. See below examples below.
*All modules have a //special attribute// called {{{__name__}}} that holds the current namespace that the module exists in. {{{__name__}}} can have two different values, depending on the state of the module: If the module is being executed directly (Meaning, not imported into another module; being executed directly from an icon, or from the command line), then {{{__name__}}} == {{{"__main__"}}}. This tells the module that //it// is currently the 'top most' \ 'root' namespace. However, if moduleA has been //imported// into moduleB, when querying {{{__name__}}} of moduleA, it will return the moduleA's name, thus showing the namespace that the module currently lives in. Uh... what? Examples!:
**Make two modules, and import one into another:
{{{
# moduleA.py
print "moduleA.__name__ = " + __name__
someVal = "spam!"
}}}
{{{
# moduleB.py
# This imports moduleA.py into the 'moduleA' namespace
import moduleA
# This will print the attribute .someVal from the
# namespace 'moduleA'
print moduleA.someVal
}}}
**And when {{{moduleB.py}}} is executed:
{{{
moduleA.__name__ = moduleA
23
}}}
** Since {{{moduleA.py}}} was imported into {{{moduleB.py}}}, {{{moduleA}}}'s {{{__name__}}} attr became //its own name//, since that was the name of the namespace it existed in. Now, if you simply ran {{{moduleA}}} from the commandline, this is what it would print:
{{{
% python moduleA.py
moduleA.__name__ = __main__
}}}
** You can see that since {{{moduleA.py}}} //wasn't// imported, //it// then defines the 'top most namespace', thus it's {{{__name__}}} attribute became {{{"__main__"}}}
*These namespaces allow code to exist relative to other code without clashing into one another. You could imagine that two different modules had functions with the same names. If you imported both modules into a third module, without having a namespace to put them in, there would be hideous nameclashing. But you can actually control what the namespace name is that you import something in to via the {{{import}}} command:
{{{
import moduleA as ma
}}}
*Simply tells the importing module that {{{moduleA}}} is now in the namespace {{{ma}}}. Furthermore, you can import specific attributes from a module if you want, rather than the whole thing:
{{{
# moduleC.py
from moduleA import someVal
print someVal
}}}
*{{{someVal}}} has been imported directly into the namespace of moduleC, so it no longer needs to be access via dot notation.
If you're wondering how to get a list of all the attributes that exist in a namespace, that's what the {{{dir}}} function is for:
{{{
print dir(myfile)
['__builtins__', '__doc__', '__file__', '__name__', 'getNamespace', 'myFunc', 'someVal']
}}}
It returns a list containing all the attributes. The ones with underscores are other 'special' attributes.
----
Also see:
*[[What's up with: if __name__ == "__main__":]]
*[[Python variable scope]]
https://pypi.python.org/pypi/nanpy
The nanpy library lets you program your Arduino via Python. Pretty slick. While the docs elude to the fact it works on multiple OS's, I've only got it to work on my Raspberry Pi: Mac, not so much. Not tried on PC.
To see all the common imports, browse here: https://github.com/nanpy/nanpy/blob/master/nanpy/__init__.py
!Installation
Be sure you have [[pip|Installing Python Packages]] previously installed.
Note you can use pip to install the Python package, but you still need to download the source from pypi above, since it contains code needed to build the new Arduino firmware.
!!Get the Arduino Software
!!!Mac
Download and install the [[Arduino App|http://arduino.cc/en/Main/Software]].
!!! Debian / Linux (Raspberry Pi)
Install Arduino on the Pi:
{{{
$ sudo apt-get install arduino
}}}
!!Get nanpy source:
Mac or Raspberry Pi. This is needed to later build the firmware.
{{{
$ cd ~
$ curl -O https://pypi.python.org/packages/source/n/nanpy/nanpy-v0.8.tar.gz
$ tar xvf nanpy-v0.8.tar.gz
$ rm nanpy-v0.8.tar.gz
}}}
!!Install Libs
Mac or Raspberry Pi:
{{{
$ pip install pyserial
$ pip install nanpy
}}}
!!Build Firmware
Mac or Raspberry Pi
Then with the Arduino plugged into the top USB port on the Pi, build the firmware:
{{{
$ cd ~/nanpy/firmware
$ export BOARD=uno
$ make
$ make upload
}}}
Mac notes:
*The {{{make}}} command wasn't available in the bash shell. As it turns out, I needed to have the latest xcode installed and the "extra command-line tools" downloaded. Xcode is free, but huge. [[This post|http://stackoverflow.com/questions/6767481/where-can-i-find-make-program-for-mac-os-x-lion]] covers it, and describes a way to install without xcode.
*{{{make}}} also gave me this error:
**{{{arduino.mk:159: *** ARDUINODIR is not set correctly; arduino software not found. Stop.}}}
**As it turns out, you need the Arduino //source// installed (along with the Mac app), //then// update that var based on where the source is installed:
{{{
$ cd ~
$ $ curl -O https://arduino.googlecode.com/files/arduino-1.0.5-src.tar.gz
$ tar xvf arduino-1.0.5-src.tar.gz
$ rm arduino-1.0.5-src.tar.gz
}}}
**Now define the {{{ARDUINODIR}}} env var based on that source:
{{{
$ export ARDUINODIR=~/arduino-1.0.5
}}}
**//Unfortunately// after all that, I get a bunch of new errors from {{{make}}}. More research is required.... :-( Here's some snippets:
{{{
make: Os: No such file or directory
make: [.lib//Users/ak_eric/arduino-1.0.5/libraries/Stepper/Stepper.cpp.o] Error 1 (ignored)
make: rcs: No such file or directory
make: *** [.lib/arduino.a] Error 1
}}}
! Examples
FYI, an Arduino must be plugged in over USB to be able to "{{{import nanpy}}}". Note the Mac always gives me {{{Error trying to connect to Arduino}}}, but the Raspberry Pi works every time.
Examples of its usage:
*http://www.raspberrypi.org/phpBB3/viewtopic.php?f=44&t=46881&p=368522&hilit=Arduino#p368522
*http://www.instructables.com/id/Arduino-Raspberry-Pi-Internet-Radio/?ALLSTEPS
Here's an example of the basic [[Blink|http://arduino.cc/en/Tutorial/Blink]] sketch ported to nanpy.
{{{
from nanpy import Arduino as A
led = 13
A.pinMode(led, A.OUTPUT)
while True:
A.digitalWrite(led, A.HIGH); # turn the LED on (HIGH is the voltage level)
A.delay(1000); # wait for a second
A.digitalWrite(led, A.LOW); # turn the LED off by making the voltage LOW
A.delay(1000);
}}}
And an example of the [[fade|http://arduino.cc/en/Tutorial/Fade]] sketch:
{{{
from nanpy import Arduino as A
led = 9
brightness = 0
fadeAmount = 5
A.pinMode(led, A.OUTPUT)
while True:
# set the brightness of pin 9:
A.analogWrite(led, brightness)
# change the brightness for next time through the loop:
brightness += fadeAmount
# reverse the direction of the fading at the ends of the fade:
if brightness == 0 or brightness == 255:
fadeAmount = -fadeAmount
# wait for 30 milliseconds to see the dimming effect
A.delay(30)
}}}
Both run just fine on my Raspberry Pi using [[Adafruits WebIDE|http://learn.adafruit.com/webide/overview]].
https://napari.org/
https://github.com/napari
napari is a fast, interactive, multi-dimensional image viewer for Python. It’s designed for browsing, annotating, and analyzing large multi-dimensional images. It’s built on top of Qt (for the GUI), vispy (for performant GPU-based rendering), and the scientific Python stack (numpy, scipy).
https://www.nature.com/articles/d41586-021-03628-7
http://docs.python.org/library/pickle.html
I recently had an issue where I'd {{{pickle}}} some data to disk, and add the data to Perforce (P4) so others could access. But when the other team members would sync to the data, they couldn't use it. They'd get an exception with this info:
{{{
No module named copy_reg
}}}
Looking online the common fix was to make sure your data was pickled in binary format. But this didn't help.
Doing some research, I found that the size of the file would get bigger after checking into P4, although when I'd diff the file it would say there were no differences. The plot thickens....
Talking with our IT department, they came to the idea that maybe P4 was changing the line ending of the files: If you open your Clientspec in P4, there is a '~LineEnd' drop-down, mine was set to 'local'. Changing this to 'unix' and resubmitting the file suddenly fixed the problem. But we couldn't have our whole team make this change, especially not knowing what other repercussions it may have, so I set it back.
So we took a look at the {{{pickle}}} docs. Come to find out, introduced in Python 2.3, there was a new 'protocol' arg provided (protocol '2') which according to the docs: "...provides much more efficient pickling of new-style classes.".
The original code was this:
{{{
outf = open(dataFile, 'wb')
pickle.dump(data, outf)
outf.close()
}}}
The new code is this:
{{{
outf = open(dataFile, 'wb')
pickle.dump(data, outf, 2)
# or this, I'm told it may be better/safer, but currently, it's still just 2 for me:
# pickle.dump(data, outf, pickle.HIGHEST_PROTOCOL)
outf.close()
}}}
Setting that new protocol value fixed the problem: The data could be added to P4, other team-members could access it no problem.
The {{{print}}} statement seems pretty obvious.
{{{
print "foo"
# foo
}}}
But it holds untapped power...
First off, print is related to {{{sys.stdout}}}. What was executed above could also be done this way:
{{{
import sys
sys.stdout.write("foo\n")
# foo
}}}
It's just a lot easier to do with {{{print}}} ;). {{{print}}} sends things to the 'standard output' ({{{stdout}}}) with some formatting added, which normally includes the addition of a return character '{{{\n}}}'.
You can however, redirect the output of print, so it goes elsewhere rather than {{{stdout}}}:
{{{
myfile = open('myfile.txt', 'w')
print >> myfile, "foo!"
myfile.close()
}}}
Will send the text {{{"foo"}}} to the file object {{{myfile}}}.
You can also redirect {{{sys.stdout}}} to dump its data elsewhere, via something like this:
{{{
import sys
orig = sys.stdout
sys.stdout = open('output.txt', 'a')
# do you printing
print "this is a test"
# reset back to orig system
sys.stdout = orig
}}}
But that's a lot of hoop-jumping required, when you can just use the {{{print}}} redirection via {{{>>}}}.
http://docs.python.org/library/functions.html#property
Properties in Python give you a way to control the way attributes on a class are accessed, set, and deleted. The above link goes through several different ways of doing it, both via the {{{property}}} //function//, and implementing the {{{property}}} function via a [[decorator|decorator]], {{{@property}}}. Below I'll show an example using both.
''Why would you want to use properties?'' Properties give you control over attribute access. The expose methods to look like attributes, so when that the user access that attribute, in fact a method is being called, and can provide an additional level of logic before the value is returned, set, or deleted.
Super simple example comparing the two in a class:
{{{
class Foo(object):
def spam(self):
return [1,2,3,4]
@property
def eggs(self):
return [1,2,3,4]
}}}
Then to access:
{{{
f = Foo()
sVal = f.spam()[3]
eVal = f.eggs[3]
}}}
As you can see, you have to //call// to {{{spam()}}} and grab the index from its return. But for {{{eggs}}} you can simply grab the index directly, like it was a list attr.
For another example, say you want to give the user the ability to modify an object's attribute, but want to make sure its within a given range (from the example below, acceptable values are from 0 -> 10). //Without// the property, if the user executed '{{{v.val = 20}}}', Python would happily oblige the request. But by making {{{val}}} a property, it's forced to use the given get, set, and delete functions, thus putting some security into your code.
This is a 'decorator property' example. This can only be used in Python 2.6 and newer.
{{{
class Foo(object):
def __init__(self):
# We put an underscore in front of the attr to tell any
# users that this should be considered 'private'...
self._val = 10
@property
def val(self):
"I'm the 'val' property"
return self._val
@val.setter
def val(self, val):
if 10 >= val >= 0:
self._val = val
else:
raise ValueError("Out of range")
@val.deleter
def delVal(self):
del self._val
v = Foo()
v.val = 5 # This calls Foo.val.setter
}}}
And this is a 'property function' example, introduced in Python 2.2.
{{{
class Foo(object):
def __init__(self):
# We put an underscore in front of the attr to tell any
# users that this should be considered 'private'...
self._val = 10
def getVal(self):
return self._val
def setVal(self, val):
if 10 >= val >= 0:
self._val = val
else:
raise ValueError("Out of range")
def delVal(self):
del self._val
val = property(getVal, setVal, delVal, "I'm the 'val' property")
v = Foo()
v.val = 20
# ValueError: Out of range
}}}
----
Also see:
*[[How can I modify an attribute any time it is accessed?]]
http://www.pyglet.org/
*"A cross-platform windowing and multimedia library for Python."
*"pyglet provides an object-oriented programming interface for developing games and other visually-rich applications for Windows, Mac OS X and Linux."
*http://steveasleep.com/pyglettutorial.html
*http://code.google.com/p/daftpython/source/browse/trunk/Starfield/starpyglet.py
I use [[Wing|Wing IDE]] as my Python IDE. It has the ability to use ''pylint''. What is pylint?
*pylint... (from their page):
>"...analyzes Python source code looking for bugs and signs of poor quality"
>"...a python tool that checks if a module satisfies a coding standard. Pylint is similar to ~PyChecker but offers more features, like checking line-code's length, checking if variable names are well-formed according to your coding standard, or checking if declared interfaces are truly implemented, and much more..."
*pylint user manual: http://www.logilab.org/card/pylint_manual
*pylint features: http://www.logilab.org/card/pylintfeatures
*Wing-pylint install docs: http://www.wingware.com/doc/edit/pylint
!!!How to install, configure, & run:
I found the docs for installing pylint a bit... scattered, so when I first installed it it failed to run. Maybe there's an easier way I completely missed, but here are the steps I used to get it working:
!!!!pylint install
*Download pylint, and put in site-packages:
**http://www.logilab.org/project/pylint
**I had to rename the extracted pylint dir from the 'version numbered version' to just "pylint".
!!!!pylint dependencies install
*In Python's {{{\site-packages}}} dir, make a {{{\logilab}}} dir. Place an empty {{{__init__.py}}} inside it (to make it a '[[package|Packages]]')
*Download 'logilab-common':
**http://www.logilab.org/project/logilab-common
**Extract to the new {{{\logilab}}} package dir. Rename extracted root dir to just "{{{common}}}".
*Download 'logilab-astng'
**http://www.logilab.org/project/logilab-astng
**Extract to the new {{{\logilab}}} package dir. Rename extracted root dir to just "{{{astng}}}".
!!!!Configure pylint in Wing
*Tools Menu -> press {{{PyLint}}} to open that ui.
*RMB in the UI, -> Configure
**This will open the {{{pylintpanel.cfg}}} Wing file.
*On the line that has '{{{command = }}}', paste in the full path to the {{{pylint.bat}}} file. Mine was here:
**{{{C:\Python26\Lib\site-packages\pylint\bin\pylint.bat}}}
*Close the cfg file.
!!!!Run pylint in Wing
*Open a module in Wing.
*In the ~PyLint window, RMB -> 'Update for <moduleName>.py'
*After doing some thinking, it should populate the various pylint 'Error', 'Warnings', & 'Info' tabs.
Should hopefully be good to go! pylint has a lot of ways to be configured, and by default it appears to be 'the most verbose'. There are options to change this, but I'm just not learning it myself...
----
I should note that after all of this I found an EasyInstall for pylint, but running that confused me even more (didn't include the pylint.bat file), so I reverted back to the above method.
{{{pywin32}}} is a package letting Python more easily interface with Windows.
Download:
*http://sourceforge.net/projects/pywin32/
Resources:
*http://win32com.goermezer.de/
[[Function]]s and [[Method]]s can both return data.
{{{
def funcA(x, y):
a = x * y
return a
foo = funcA(5.0, 10.0)
# 50.0
}}}
However, the {{{return}}} statement can actually return back multiple objects, but it returns them as a single {{{tupple}}}:
{{{
def funcB(x, y):
a = x / y
b = y * x
return a, b
foo = funcB(5.0, 10.0)
# (0.5, 50.0)
}}}
But if we expect the tupple, we can unpack it:
{{{
foo, goo = funcB(5.0, 10.0)
print foo
# 0.5
print goo
# 50.0
}}}
[[Python docs|http://docs.python.org/ref/return.html]] for {{{return}}}.
https://scikit-learn.org/stable/index.html
<<<
scikit-learn is a Python module integrating classic machine learning algorithms in the tightly-knit scientific Python world (numpy, scipy, matplotlib). It aims to provide simple and efficient solutions to learning problems, accessible to everybody and reusable in various contexts: machine-learning as a versatile tool for science and engineering.
<<<
Since Python 2.4, they've introduced the built-in types {{{set}}} and {{{frozenset}}}:
Docs:
http://docs.python.org/library/stdtypes.html#set
A great overview of {{{set}}} methods and operands can be found here:
https://realpython.com/python-sets/#operators-vs-methods
Set Creation
{{{
s1 = set([1,2,3])
s2 = set([3,4,5])
# or:
s1 = {1,2,3}
s2 = {3,4,5}
}}}
Union examples:
{{{
s3 = s1|s2
print s3
s4 = set.union(s1, s2)
print s4
s5 = s1.union(s2)
print s5
s6 = s1.union( [3,4,5] )
s1 |= s2
print s1
}}}
{{{
# all print
set([1, 2, 3, 4, 5])
}}}
I often do type checks against strings, and do things if strings are found:
{{{
if type(myVar) == type(""):
# do something
}}}
However, there are different types of strings, an the above example can easily fail:
{{{
print type(u"")
print type(r"")
print type("")
<type 'unicode'>
<type 'str'>
<type 'str'>
}}}
To solve for this, we can compare against the superclass of all strings, {{{basestring}}}:
{{{
if issubclass(type(myVar), basestring):
# do stuff
}}}
Some notes to remind me the basics of the '{{{with}}}' statement.
In a nutshell, it lets you wrap a block of code in a 'context' that controls how that block will be entered, and exited. It also catches exceptions for you, and returns any that occurred, so it takes care of the {{{try}}}\{{{except}}} clause automatically.
----
http://docs.python.org/reference/datamodel.html#context-managers
http://docs.python.org/reference/compound_stmts.html#with
http://docs.python.org/library/stdtypes.html#context-manager-types
http://www.python.org/dev/peps/pep-0343/
A sample context manager:
{{{
class CtxManager(object):
"""
A context manager object. Has two methods, each which support a special
type of return.
"""
def __enter__(self):
"""
Called when the context is entered.
return : Can return itself (or another object related to the context) to
provide data from this context to the enclosed block, and will be
persistent when the with clause exits.
"""
print "Entering Context!"
self.data = 23
# If you don't return self, you can't access this object inside the with clause:
return self
def __exit__(self, exc_type, exc_value, traceback):
"""
Called when the contex is exited.
exc_type : If there is an Exception, the type. Otherwise None
exec_value : If there is an Exception, the value. Otherwise None
traceback : If there is an Exception, the traceback. Otherwise None
return : True \ False : If False, and there was an exception, re-raise the
exception. If True and there was an exception, handle the exception
silently.
"""
if exc_type:
print "Exiting Context, caught exceptions:", exc_type, exc_value
else:
print "Exiting Context!"
return True
}}}
And to put it in action, you use this type of syntax. Notice how you can access the instanced object {{{a}}} //outside// of the with clause? This allows a context manager to (among other things) track the data it's managing, and expose the results to you later.
{{{
with CtxManager() as a:
print "\tInside 'CtxManager()'"
# Access data from the context itself:
print "\tContext data:", a.data
a.data = "42"
print "Outside data update:", a.data
}}}
prints:
{{{
Entering Context!
Inside 'CtxManager()'
Context data: 23
Exiting Context!
Outside data update: 42
}}}
----
Optionally, you can skip a bunch of the cruft using the [[contextlib.contextmanager|https://docs.python.org/2/library/contextlib.html#contextlib.contextmanager]] decorator:
{{{
from contextlib import contextmanager
@contextmanager
def myCM(data):
print "Stuff Before: %s" % data
yield
print "Stuff After: %s" % data
>>> with myCM("mystuff"):
... print "Stuff in the middle"
...
Stuff Before: mystuff
Stuff in the middle
Stuff After: mystuff
}}}