Planet Python
Last update: March 18, 2018 04:48 AM
March 17, 2018
Weekly Python StackOverflow Report
(cxvii) stackoverflow python report
These are the ten most rated questions at Stack Overflow last week.
Between brackets: [question score / answers count]
Build date: 2018-03-17 21:06:31 GMT
- Does 'finally' always execute in Python? - [61/4]
- Is it possible to "hack" python's print function? - [42/2]
- In python, is there some kind of mapping to return the "False value" of a type? - [24/6]
- How to efficiently find the indices of matching elements in two lists - [10/5]
- how to print a tuple of tuples without brackets - [6/5]
- Inverting floats in a list of lists - [6/4]
- Why does numpy.savez() output non reproducible files? - [6/1]
- New to Python, don't know what is wrong with my code - [5/4]
- cant iterate nested for loop as wanted -python -maybe a simple mistake - [5/3]
- Creating a tree without duplicates - [5/2]
Nikola
Nikola v7.8.12 is out! (maintenance release)
On behalf of the Nikola team, I am pleased to announce the immediate availability of Nikola v7.8.12. This is a maintenance release for the v7 series.
Future releases in the v7 series are going to be small maintenance releases that include bugfixes only, as work on v8.0.0 is underway.
What is Nikola?
Nikola is a static site and blog generator, written in Python. It can use Mako and Jinja2 templates, and input in many popular markup formats, such as reStructuredText and Markdown — and can even turn Jupyter Notebooks into blog posts! It also supports image galleries, and is multilingual. Nikola is flexible, and page builds are extremely fast, courtesy of doit (which is rebuilding only what has been changed).
Find out more at the website: https://getnikola.com/
Changes
- Fix loading non-default languages
Catalin George Festila
The Google Cloud SDK - part 003 .
The webapp2 is a lightweight Python web framework compatible with Google App Engine’s.
The webapp2 project, by Rodrigo Moraes, started as a fork of the App Engine webapp framework.
The webapp2 includes a number of features such as improved support for URI routing, session management and localization.
You can see google documentation about this python module this link.
They say:
"webapp2 is compatible with the WSGI standard for Python web applications. You don't have to use webapp2 to write Python applications for App Engine. Other web application frameworks, such as Django, work with App Engine, and App Engine supports any Python code that uses the CGI standard. "
This is default start python example from Google Cloud SDK tested in the last tutorial.
import webapp2
class MainPage(webapp2.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/plain'
self.response.write('Hello, World!')
app = webapp2.WSGIApplication([
('/', MainPage),
], debug=True)Remember how to deploy your project to google:C:\Python27>cd python-docs-samples\appengine\standard\hello_world
C:\Python27\python-docs-samples\appengine\standard\hello_world>gcloud app deploy app.yaml
Services to deploy:
descriptor: [C:\Python27\python-docs-samples\appengine\standard\hello_world\app.yaml]
source: [C:\Python27\python-docs-samples\appengine\standard\hello_world]
target project: [xxxxxx]
target service: [default]
target version: [xxxxxxxxxxxxx]
target url: [https://xxxxxx.appspot.com]
Do you want to continue (Y/n)? y
Beginning deployment of service [default]...Now I make some changes into main.py file to show you how easy is to use it.This file: main.py is set into setting file app.yaml like: script: main.app.
Let's make some changes.
The default project is set with --promote true the result is : after a number of upload you got this error:
ERROR: (gcloud.app.deploy) Error Response: [400] Your app may not have more than 15 versions.Please delete one of the existing versions before trying to create a new version.
...To fix go to App Engine - Versions with selected versions and press Delete button.Then you can make the upload with command :
gcloud app deploy app.yamlAlso you can use this:gcloud app deploy app.yaml --stop-previous-versionSome info about your project can be see with this command:gcloud config listYou can see the gcloud versions with:gcloud versionI tested also with python version 3.6.4 :C:\Python364\Scripts>pip install webapp2
Requirement already satisfied: webapp2 in c:\python364\lib\site-packages
2 python-dateutil-2.7.0 setuptools-39.0.0
Codementor
Two cool features of Python NumPy: Mutating by slicing and Broadcasting
NumPy is pure gold. It is fast, easy to learn, feature-rich, and therefore at the core of almost all popular scientific packages in the Python universe (including SciPy and Pandas, two most widely used packages for data science and statistical modeling). In this article, let us discuss briefly about two interesting features of NumPy viz. mutation by slicing and broadcasting.
March 16, 2018
Doug Hellmann
openstack-summit-counter 0.2.0
openstack-summit-counter is a plugin for python-openstackclient, the command line tool for interacting with OpenStack. This plugin helps you answer the summit registration question about how many summits you have attended in the past. What’s new in 0.2.0? Add support for counting PTGs (contributed by Colleen Murphy)
Weekly Python Chat
Making Python GUIs with BeeWare
Have you ever wondered how to make GUI applications in Python? Have you tried making Python-powered GUI apps and found it painful?
This week's chat is about making cross-platform GUI applications using BeeWare.
We're joined by a special guest this week: Russell Keith-Magee, the BeeWare founder.
Russell will start the chat by demoing BeeWare and then he'll answer your questions about using BeeWare for making GUI applications.
Codementor
Python is the Perfect Tool for any Problem
https://cdn-images-1.medium.com/max/1600/0*UiI1SaCbMvovF2wh. Reflecting on my first Python program Reflection is always a helpful (and sometimes entertaining ) exercise. For nostalgia’s sake — if...
Doug Hellmann
openstack-summit-counter 0.1.0
openstack-summit-counter is a plugin for python-openstackclient, the command line tool for interacting with OpenStack. This plugin helps you answer the summit registration question about how many summits you have attended in the past. This is the first public release.
Codementor
How to rewrite your SQL queries in Pandas, and more
Introduction to Pandas, for developers already familiar with SQL.
Peter Bengtsson
Worlds simplest web scraper bot in Python
I just needed a little script to click around a bunch of pages synchronously. It just needed to load the URLs. Not actually do much with the content. Here's what I hacked up:
import random
import requests
from pyquery import PyQuery as pq
from urllib.parse import urljoin
session = requests.Session()
urls = []
def run(url):
if len(urls) > 100:
return
urls.append(url)
html = session.get(url).decode('utf-8')
try:
d = pq(html)
except ValueError:
# Possibly weird Unicode errors on OSX due to lxml.
return
new_urls = []
for a in d('a[href]').items():
uri = a.attr('href')
if uri.startswith('/') and not uri.startswith('//'):
new_url = urljoin(url, uri)
if new_url not in urls:
new_urls.append(new_url)
random.shuffle(new_urls)
[run(x) for x in new_urls]
run('http://localhost:8000/')
If you want to do this when the user is signed in, go to the site in your browser, open the Network tab on your Web Console and copy the value of the Cookie request header.
Change that session.get(url) to something like:
html = session.get(url, headers={'Cookie': 'sessionid=i49q3o66anhvpdaxgldeftsul78bvrpk'}).decode('utf-8')
Now it can spider bot around on your site for a little while as if you're logged in.
Dirty. Simple. Fast.
Codementor
Create a Video Course!!!
I am interested in creating video tutorials on hot and upcoming technologies like #Java, #Python, #R, #DeepLearning, #Artificial Intelligence, #DevOps, #AWS, etc. and I'm looking for experienced...
Blue Yonder Tech
PyCon.DE Part 4: Observing applications with Sentry and Prometheus
In Part 4 of our PyCon.DE series we´ll demonstrate how to observe your applications with Sentry and Prometheus. If you have services running in production, something will fail sooner or later. We cannot avoid this completely, but we can prepare for … Read More
Der Beitrag PyCon.DE Part 4: Observing applications with Sentry and Prometheus erschien zuerst auf Blue Yonder Technology Blog.
Talk Python to Me
#155 Practical steps for moving to Python 3
Since 2008 there has been this tension in Python where the much of the effort to improve Python has been on Python 3 whereas many developers were left stuck on Python 2 primarily because important packages were not yet Python 3 capable.
Martin Fitzpatrick
15 Minute Apps
A collection of 15 small — minute — desktop applications written in Python using the PyQt framework. These apps are intended as examples from which you can poke, hack and prod your way to writing your own tools.
The apps
The apps showcase various parts of the Qt framework, including advanced widgets, multimedia, graphics views and decorationless windows. However, the most generally interesting/feature complete applications are Minesweeper, Solitaire and Paint.
The source code for all apps is available in the Github repository. All code is MIT licensed and free to use to in your own projects.
Web Browser - "MooseAche"

An example web browser built with Python and Qt. Using the QtWebEngineWidgets system introduced in Qt5.6, this provides a single-window browsing experience with the usual controls, as well as saving and loading HTML.
Web Browser (tabbed) — "Mozzarella Ashbadger"

Mozarella Ashbadger is the latest revolution in web browsing! Go back and forward! Print! Save files! Get help! (you’ll need it). Any similarity to other browsers is entirely coincidental.
Minesweeper — "Moonsweeper"

Explore the mysterious moon of Q'tee without getting too close to the alien natives!
Moonsweeper is a single-player puzzle game. The objective of the game is to explore the area around your landed space rocket, without coming too close to the deadly B'ug aliens. Your trusty tricounter will tell you the number of B'ugs in the vicinity.
Notepad — "No2Pads"

A very simple notepad clone using the QTextEdit widget to handle more or less everything. Supports file loading, saving and printing.
Calculator — "Calculon"

A simple calculator application implemented in Python using PyQt. The UI was designed in Qt Designer and the calculator operations are implemented using simple stack-based logic.
Word Processor — "Megasolid Idiom"

The word processor for all your small, poorly formatted documents. An extension of the notepad, again using a QTextEdit but with rich text editing enabled.
Webcam/Snapshot — "NSAViewer"

With this webcam snapshot application you can take photos of what is currently being viewed by your webcam. Uses the Qt QtMultimedia framework for handling all the interaction with the camera, and supports multiple cameras if you have them.
Media Player — "Failamp"

Simple app to listen to and watch videos and audio files, with built in playlist. Uses QtMultimedia and QtMultimediaWidgets to handle playback and manage the playlist.
Post-it Notes - "Brown Note" (QtDesigner)

Take temporary notes on your desktop, with this floating-note app. Notes are stored locally in a SQLite database.
Paint - "Piecasso" (QtDesigner)

Express yourself with PieCasso, the only painting app to feature ready made pictures of pie.
Piecasso is a clone of the Paint programme from Windows 95 (ish) with a few additions (and subtractions). The programme features standard tools including pen, brush, fill, spray can, eraser, text and a number of shapes.
Unzip - "7Pez" (QtDesigner)

Unzip your files with a cat. Drag-drop your zip file onto the floaty cat, and fill up it's Pez-file repository. Press the head to release the Pez (your files) into the same folder.
Translator - "Translataarrr" (QtDesigner)

A translator from any language (supported by Google translate) to pirate. This uses a remote API from http://api.funtranslations.com for English to Pirate translation, and a unofficial Python wrapper around Google translate for other languages to English.
Weather - "Raindar" (QtDesigner)

Get your daily weather and 15hr forecast. Data is provided by the free weather and forecast API from https://openweathermap.org/
Currency converter - "Doughnut" (PyQtGraph)

This is a simple currency exchange rate tracker implemented in PyQt, using the fixer.io API for data. The default setup shows currency data for the preceding 180 days.
Solitaire - "Ronery" (QGraphicsScene)

The classic card Solitaire (Klondike) game with a North Korea / Team America: World Police theme. The game is otherwise identical, offering the same options. Built with PyQt, it uses QGraphicsScene to handle the play area.
Getting started
To use each app you first need to install the requirements. In most cases the only requirements are PyQt5, and occasionally requests (for http requests). To install app-specific requirements change to the folder of the app and run:
pip3 install -r requirements.txt
Once the requirements are installed, you can run the app using Python 3.
python3 <filename>.py
The application window should appear.
License
All code is licensed under an MIT license. This allows you to re-use the code freely, remixed in both commercial and non-commercial projects. The only requirement is to include the same license when distributing.
The intent here is to allow as many people as possible to make use of this code, so you if you have specific license requirements or questions, feel free to ask — the answer is probably "yes."
Icons used in the applications are by Yusuke Kamiyaman.
March 15, 2018
Rene Dudfield
Drawing sound (as a waveform in pygame).
There's an infinite number of ways to visualize sound. A classic way is to draw it as a waveform.
![]() |
| Sound samples drawn as a Waveform. Scaled into a 320x200 sized Surface. |
A sound could be made up of 44100 samples per second. Where each sample is often a 16 bit number (or 8bit or a 32bit floating point).
Python comes with a built in array for efficiently storing numbers. We can store samples in there, with integers between -32768 and 32768. This is a signed 16bit(2 byte) number. Two to the power of 16 is 65536, and if we divide that by two we see the minimum and maximum value that can hold. pow(2, 16) / 2 == 32768.
Below is the annotated code, also with an example of an array of samples representing a square wave.
We loop over the samples and draw a line from the previous sample to the current one. 0 to 1, 1 to 2, 2 to 3, ... N-1 to N.
You can also find it in the pygame CookBook at https://www.pygame.org/wiki/DrawWaveform
(maybe easier to read than on this blog)
# python built in array type is useful for storing sound data.
import array
# a square wave tone, with sample values between -32766 and 32766.
samples = array.array('h', [32766, 32766, 32766, 32766, 32766, 32766,
32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766,
32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766,
32766, 32766, 32766, 32766, -32766, -32766, -32766, -32766,
-32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766,
-32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766,
-32766, -32766, -32766, -32766, -32766, -32766, -32766])
def scale_samples_to_surf(width, height, samples):
""" Returns a generator containing (x, y) to draw a waveform.
:param width: width of surface to scale points to.
:param height: height of surface to scale points to.
:param samples: an array of signed 1 byte or signed 2 byte.
"""
assert samples.typecode in ['h', 'b']
# precalculate a bunch of variables, so not done in the loop.
len_samples = len(samples)
width_per_sample = width / len_samples
height_1 = height - 1
if samples.typecode == 'h':
# for array typecode 'h', -32768 to 32768
factor = 1.0 / 65532
normalize_modifier = int(65532 / 2)
elif samples.typecode == 'b':
# for array typecode 'b', -127 to 127
factor = 1.0 / 256
normalize_modifier = int(256 / 2)
return ((
int((sample_number + 1) * width_per_sample),
int(
(1.0 -
(factor *
(samples[sample_number] + normalize_modifier)))
* (height_1)
))
for sample_number in range(len_samples))
def draw_wave(surf,
samples,
wave_color = (0, 0, 0),
background_color = pg.Color('white')):
"""Draw array of sound samples as waveform into the 'surf'.
:param surf: Surface we want to draw the wave form onto.
:param samples: an array of signed 1 byte or signed 2 byte.
:param wave_color: color to draw the wave form.
:param background_color: to fill the 'surf' with.
"""
assert samples.typecode in ['h', 'b']
if background_color is not None:
surf.fill(background_color)
width, height = surf.get_size()
points = tuple(scale_samples_to_surf(width, height, samples))
pg.draw.lines(surf, wave_color, False, points)
# Here we should how to draw it onto a screen.
waveform = pg.Surface((320, 200)).convert_alpha()
draw_wave(waveform, samples)
screen.fill((255, 255, 255))
screen.blit(waveform, (160, 100))
Wallaroo Labs
Your Wallaroo Questions Answered
Wallaroo Labs has received a lot of great feedback from developers on Hacker News and other communities. Below are some answers to questions that repeatedly come up in conversations about Wallaroo. Thank you! Please keep reading our engineering posts, commenting, and asking questions! Why did you write Wallaroo in Pony? When we looked at the tools available to build Wallaroo and the use cases we wanted to handle, there were a few paths available to us.
Continuum Analytics Blog
March 2018 Kubernetes Security Vulnerabilities and Anaconda Enterprise
The Anaconda team tracks security vulnerabilities and CVEs via the National Vulnerability Database (NVD) on an ongoing basis. Our team is committed to the security of Anaconda Enterprise by making updates available in a timely manner in response to security vulnerabilities and similar incidents. Two security vulnerabilities (CVE-2017-1002101 and CVE-2017-1002102) were recently identified in Kubernetes, which …
Read more →
Tryton News
Foundation Budget 2018
CC BY 2.0
TaxCredits.net
Budget for 2018
The Foundation has decided to publish a budget for 2018. This is the result of requests from the community will to know what are the plans of the Foundation. Of course as the revenue of the Foundation relies only on donation, we can not guarantee that every things will be realized. Indeed we have ordered the points by priority. Each point will be activated once we have we reach its donation level.
We will like to thank everyone who donated to the foundation. Here are the donations from past years. Thanks to previous year donations, we started the redesing of the website. The first proposal is now available.
Budget points
- 500€: Infrastructure (rental and maintenance of servers).
- 750€: Miscellaneous management fees.
- 1300€: Buy a new mac mini for better MacOS support.
- 5300€: Organization of first hackathon by inviting key developers for a week-end.
- 10000€: Organization of a documentation writing hackathon by inviting key developers and end-users for a week-end.
You can help the Foundation by making a donation. We will apreciate to get enought donations before the next tryton release, scheduled for 23th of April, in order to buy a new mac mini so we can improve the MacOS support.
Codementor
Multiclass Classification using Random Forest on Scikit-Learn Library
Building a Random Forest classifier (multi-class) on Python using SkLearn.
March 14, 2018
NumFOCUS
NumFOCUS thanks Matt Turk for his service on the Board of Directors
The post NumFOCUS thanks Matt Turk for his service on the Board of Directors appeared first on NumFOCUS.
PyCharm
PyCharm 2018.1 EAP 9
This week’s EAP version is now available: get it now from our website.
New in PyCharm
Flask Run Configuration
If you’ve been using a recent version of Flask, you may have already used the flask run commands to start your development server. PyCharm now comes with a special run configuration type to make use of Flask’s new functionality. Try it now!
Further Improvements
- In the previous EAP, in some cases, the sudo password was asked upon creation of a new virtualenv. This bug has been resolved.
- Various improvements to the ‘Add type hint’ intentions. To have PyCharm suggest a type hint, just put your cursor on a variable, press Alt+Enter, and choose one of the options.
- The scroll behavior in the built-in terminal (Alt+F12) has been improved.
- Read more about new features in the release notes
Interested?
Download this EAP from our website. Alternatively, you can use the JetBrains Toolbox App to stay up to date throughout the entire EAP.
If you’re on Ubuntu 16.04 or later, you can use snap to get PyCharm EAP, and stay up to date. You can find the installation instructions on our website.
PyCharm 2018.1 is in development during the EAP phase, therefore not all new features are already available. More features will be added in the coming weeks. As PyCharm 2018.1 is pre-release software, it is not as stable as the release versions. Furthermore, we may decide to change and/or drop certain features as the EAP progresses.
All EAP versions will ship with a built-in EAP license, which means that these versions are free to use for 30 days after the day that they are built. As EAPs are released weekly, you’ll be able to use PyCharm Professional Edition EAP for free for the duration of the EAP program, as long as you upgrade at least once every 30 days.
Rene Dudfield
Sound generation pygame examples.
Here's a few sound generation examples with pygame (and no numpy/scipy).
If there's interest I'll expand this into a bigger example? Let me know.
All the basics for making a music program (sampler/synth).
- some sample rate conversion,
- bit rate conversion
- tone generation using generators (square wave)
- python arrays used as buffers for pygame.Sound (zero copy).
""" Some examples for generating and converting sounds for pygame.
Python 2.7, 3.6
Shows:
- a simple 'square wave' generated
- resampling sample rates (eg, 8363 to 44100)
- using built in python array for making pygame.Sound samples.
- samples at different bit sizes
- converting from signed 8 to signed 16bit
- how initializing the mixer changes what samples Sound needs.
- Using the python stdlib audioop.ratecv for sample rate conversion.
Square Wave
https://en.wikipedia.org/wiki/Square_wave
MOD (file format)
https://en.wikipedia.org/wiki/MOD_(file_format)
pygame.mixer.get_init
https://www.pygame.org/docs/ref/mixer.html#pygame.mixer.get_init
pygame.Sound
https://www.pygame.org/docs/ref/mixer.html#pygame.mixer.Sound
array (python stdlib)
https://docs.python.org/3/library/array.html
wave (python stdlib)
https://docs.python.org/3/library/wave.html
audioop.ratecv (python stdlib)
https://docs.python.org/3/library/audioop.html?highlight=audio#audioop.ratecv
"""
from array import array
import pygame as pg
class Tone(pg.mixer.Sound):
"""This generates a 'Square wave' with a generator.
Then creates an array of samples, and passes that into pygame.Sound.
"""
def __init__(self, frequency, array_type, volume=.1):
self.frequency = frequency
if array_type == 'b':
# we have to convert the 1 byte 'b' samples to 2 byte 'h'.
samples = self.signed_char_to_signed_short(
self.make_samples_b()
)
elif array_type == 'h':
samples = self.make_samples_h()
else:
raise ValueError('array_type not supported')
pg.mixer.Sound.__init__(self, buffer=samples)
self.set_volume(volume)
def make_samples_b(self):
""" Builds samples array between -127 and 127.
Array type 'h'.
"""
mixer_frequency = pg.mixer.get_init()[0]
mixer_format = pg.mixer.get_init()[1]
period = int(round(mixer_frequency / self.frequency))
max_amplitude = 2 ** (abs(mixer_format) - 1) - 1
max_amplitude = int(max_amplitude / 256)
# print(f'mixer_frequency:{mixer_frequency}, mixer_format:{mixer_format}')
# print(f'period:{period}, max_amplitude:{max_amplitude}')
# 'b' array is signed char, 1 byte
# https://docs.python.org/3/library/array.html
samples = array('b',
(max_amplitude if time < period / 2 else -max_amplitude
for time in range(period))
)
return samples
def signed_char_to_signed_short(self, b_samples):
""" Converts 1 byte signed char samples to 2 byte signed short.
127 to 32767
"""
# just a simple linear conversion.
factor = int(32767 / 127)
return array('h', (sample * factor for sample in b_samples))
def make_samples_h(self):
""" Builds samples array between -32767 snd 32767.
Array type 'h'.
"""
mixer_frequency = pg.mixer.get_init()[0]
mixer_format = pg.mixer.get_init()[1]
period = int(round(mixer_frequency / self.frequency))
max_amplitude = 2 ** (abs(mixer_format) - 1) - 1
# print(f'mixer_frequency:{mixer_frequency}, mixer_format:{mixer_format}')
# print(f'period:{period}, max_amplitude:{max_amplitude}')
# 'h' array is signed short, 2 bytes
# https://docs.python.org/3/library/array.html
samples = array('h',
(max_amplitude if time < period / 2 else -max_amplitude
for time in range(period))
)
return samples
class Sample(pg.mixer.Sound):
""" For playing a sample.
Takes a file, and reads it in as 8bit signed data.
Then converts it to the 16bit signed size the pygame.mixer needs.
"""
def __init__(self, fname, volume=.1):
with open(fname, 'rb') as f:
samples = self.signed_char_to_signed_short (
array('b', f.read())
)
pg.mixer.Sound.__init__(self, buffer=samples)
self.set_volume(volume)
def signed_char_to_signed_short(self, b_samples):
""" Converts 1 byte signed char samples to 2 byte signed short.
127 to 32767
"""
# just a simple linear conversion.
import time
t0=time.time()
factor = int(32767 / 127)
samples = array('h', (
max(sample, -127) * factor if sample < 0 else
min(sample, 127) * factor
for sample in b_samples))
t1=time.time()
print(t1-t0)
return samples
def fetch_example_mod_file(mod_fname):
""" Grab a file that has a sound samples in it from the net.
'MOD is a computer file format used primarily to represent music,
and was the first module file format. MOD files use the ".MOD"
file extension, except on the Amiga which doesn't rely on
filename extensions, instead it reads a file's header to
determine filetype. A MOD file contains a set of instruments in
the form of samples, a number of patterns indicating how and when
the samples are to be played, and a list of what
patterns to play in what order.'
https://en.wikipedia.org/wiki/MOD_(file_format)
"""
import os
url = 'https://api.modarchive.org/downloads.php?moduleid=101996'
if not os.path.exists(mod_fname):
import urllib2
print ('Fetching %s .mod into file: %s' % (url, mod_fname))
data = urllib2.urlopen(url).read()
with open(mod_fname, 'w') as modf:
modf.write(data)
def resample(mod_fname):
""" An example of resampling audio to a different framerate.
eg, from 8363 one byte samples per second to
44100 two byte samples per second.
"""
import audioop
import wave
from io import BytesIO
in_framerate = 8363
in_sampwidth = 1
in_nchannels = 1
out_framerate = 44100
num_seconds = 5
with open(mod_fname, 'rb') as f:
# Throw away the start data of this mod file.
# Better samples later on.
f.read(8363*2)
in_frame_data = f.read(in_framerate * num_seconds)
# https://docs.python.org/3/library/audioop.html?highlight=audio#audioop.ratecv
newfragment, newstate = audioop.ratecv(
in_frame_data,
in_sampwidth,
in_nchannels,
in_framerate,
out_framerate,
None)
# print(f'len(newfragment):{len(newfragment)}')
# A perfect conversion is not possible, because the sample
# rates do not divide equally. However, the number
# of samples should be close.
assert (out_framerate * num_seconds) - len(newfragment) < 10
pg.mixer.Sound(buffer=newfragment).play(-1)
# TODO:
# Converting between modo and stereo?
# audioop.tomono and audioop.tostereo
# https://docs.python.org/3/library/audioop.html?highlight=audio#audioop.tomono
# How to draw a wave form?
# using pygame.draw.lines transforming audio into
# Surface space.
# Meaning, scaling audio samples into a particular
# sized part of the screen.
# More sound generator types.
# Saw tooth.
if __name__ == "__main__":
# https://www.pygame.org/docs/ref/mixer.html#pygame.mixer.init
pg.mixer.pre_init(44100, -16, 1, 1024)
pg.init()
pg.display.set_caption('Playing square wave, 808 frequency')
pg.display.set_mode((320, 200))
mod_fname = 'outrun_3.mod'
fetch_example_mod_file(mod_fname)
# play on repeat, -1 means loop indefinitely.
# https://www.pygame.org/docs/ref/mixer.html#pygame.mixer.Sound.play
if 0:
Tone(frequency=808, array_type='b').play(-1)
if 0:
try:
Sample(mod_fname).play(-1)
except IOError:
print ('no %s' % mod_fname)
if 0:
pg.mixer.music.load(mod_fname)
pg.mixer.music.play()
if 1:
resample(mod_fname)
going = True
while going:
for e in pg.event.get():
if e.type in [pg.QUIT, pg.KEYDOWN]:
going = False
Anwesha Das
Setting up my own server
A long, long time ago a mortgage lawyer started to write her blog, just to get familiar with several crazy newfangled things called computers and the internet by using them to do something she liked, writing. So she started writing a blog using something called Wordpress.
The aim of the blog, was to explain legal terms, and theories in simple intelligible language. The blog was called lawexplainedindia.
Time flew; and with life’s funny, yet inevitable twists and turns, the lawyer landed into the world of computers; the world of Free & open source software and technology. So, the blog changed its face and got a new home at
https://anweshadas.in. It portrays what I think, and read, but not solely law now.
All these years, however I never took the responsibility of maintaining the website. Kushal, being the wonderful partner he is, used to do this painful job for me. He use to maintain it using a self hosted Ghost blog (Version 0.11.x).
I recently decided to take back the burden from Kushal. It would give me the opportunity of learning something new, becoming more familiar with the world of Free Software. I am now using a Digital Ocean droplet where the base operating system is CentOS 7. Setting that up was the easy part. Securing it and getting the blog to work, took some doing though. Here’s what I did …
Setup the firewall:
The first job was to setup the firewall rules to provide safety from the untrusted external network. I religiously followed Mohamed Raiyen’s post on hardening server security. That gave the droplet at least a semblance of safety.
Using official Ghost docker image
I wanted to use the latest Ghost as a platform to publish my blog.
There are two ways of doing that :
- Ghost can maintain it for you, for a monthly or yearly subscription.
- You can self host and maintain it yourself.
I opted for the second, by using the official docker container image.
The new ghost version provides an updated theme (Casper v2), but I liked my older version better. I copied my old theme (edited as required), all the images, and content into a directory /data.
The security context of the directory needed to be changed to access it inside the container by the following command
chcon -R -t svirt_sandbox_file_t /data
At PyCon US 2017, I had requested John Hawley to explain containers to me in a very naive non-technical way, one that a 10 year old would get.
Here’s how he put it …
“Imagine lots of little piggies in a sty. You have several naughty ones, which you do not want to get out of their own space and go into others.
Now the same theory applies to containers.
Here each sty is a container, where you are stopping your troublesome piglets (applications/programs) getting into others spaces.”
After this uh, interesting introduction, as I started to read more about containers, I came across an interesting comment by Dan Walsh that “Containers do not contain”, with a subsequent caution that if you want to use containers, one should use them following proper security measures.
This was the first time for me to use containers.
I played around with docker for few days before I used it here.
I am mounting the /data directory (from my machine) into /var/lib/ghost/content (in the container), as that is the content directory for ghost.
Now we can store the data even after the container stops running. I use the command below to start the docker container
docker run -d --name xyz -p 127.0.0.1234:2368 -v /data:/var/lib/ghost/content ghost:1.21.4
nginx as reverse proxy
I am using the nginx as the reverse proxy to the container. I also copy pasted the TLS certificates from Let’s Encrypt into the correct directory.
I will be writing about how to get a ssl certificate from lets encrypt in a subsequent blog post.
This particular project taught me to do several things at the same time, (all completely new to me) and gave me the real life production feeling :)
I learned each of these elements (docker, nginx, setting up a firewall, getting SSL certificates,) separately, and then combined them together as per the needs of the project — my shiny new blog. Though it took me a lot of time, frustration and a realization that the machine called computer is truly unpredictable (even more so than my unpredictable 3 year old). But at the end of all, when I witnessed my blog running at https://anweshadas.in, it was amazing.
Catalin George Festila
The regex online tool for python and any programming languages.
Today I tested this online tool.
Is a tool for regular expression (regex or regexp for short) for many progamming languages.
This programming languages are : php, javascript , golang and python.
The tool is easy to use it.
First you need to select the programming language that is used for regular expression.
The next step is to put the regular expression into edit box and add your text to be parsed by this regular expression.
For example if you use this inputs for regular expression:
([a-zA-Z]+) \d+
and this text example:
March 7 1976, June 1, August 9, Dec 25
the result output will be this:
March , June , August , Dec
Mike Driscoll
10 Years of Mouse Vs the Python
When I first started this blog, ten years ago today, I never thought I would be blogging about Python for a decade. In fact, the very first post wasn’t even about the Python language itself, but about me going to PyCon in Chicago. In fact, I wrote 7 articles about that first PyCon event before I wrote my very first tutorial-like article, which happened to be about reading OpenVPN’s status using wxPython and PyWin32.
Frankly this blog wouldn’t exist at all if there wasn’t a few readers that reached out to me to tell me how helpful the blog was or to put in article requests. Because of that encouragement, I continued writing and Python ended up being one of my passions. In fact, the continued encouragement and suggestions led me to writing my first book, Python 101, as well.
I don’t know if blogging will still be popular in another ten years, but if people continue to enjoy my content than I will continue to keep writing it. Thanks for all your support and happy coding!


