skip to navigation
skip to content

Planet Python

Last update: March 19, 2019 07:47 PM UTC

March 19, 2019


PyCoder’s Weekly

Issue #360 (March 19, 2019)

#360 – MARCH 19, 2019
View in Browser »

The PyCoder’s Weekly Logo


How to Build a Python GUI Application With wxPython

In this step-by-step tutorial, you’ll learn how to create a cross-platform graphical user interface (GUI) using Python and the wxPython toolkit. A graphical user interface is an application that has buttons, windows, and lots of other widgets that the user can use to interact with your application.
REAL PYTHON

Simplify Your Python Developer Environment

How three tools (pyenv, pipx, pipenv) make for smooth, isolated, reproducible Python developer and production environments.
MASON EGGER • Shared by Mason Egger

Automated Code Reviews for Python

alt

Take the hassle out of code reviews—Codacy flags errors so you can fix them quickly. Address security concerns, code duplication, code complexity and drops in coverage, directly from your workflow. Click here to get started →
CODACY sponsor

When C Extensions Crash: Easier Debugging for Your Tests

Learn how to prepare for crashes in advance, so when they do occur you can quickly figure out which part of the codebase caused them: The standard library’s faulthandler, verbose test runs, package listing, and catchsegv on Linux.
ITAMAR TURNER-TRAURING

Why Operators Are Useful

Latest blog post from Guido, related to the recent discussion about Python getting + and - operators for merging dictionaries (PEP 584).
GUIDO VAN ROSSUM • Shared by Ricky White

Python Decorators 101

See step-by-step what Python decorators are and how you can use them to make your own code more Pythonic and expressive.
REAL PYTHON video

Tuple Ordering and Deep Comparisons in Python

Nice deep dive on comparison operators in Python.
TREY HUNNER • Shared by Ricky White

urllib CRLF Injection Vulnerability

The current Python 2.x and 3.x implementation of urllib does not encode the \r\n sequence in the query string, which allows an attacker to manipulate a HTTP header with the \r\n sequence in it, so the attacker can insert arbitrary content to the new line of the HTTP header.
PYTHON.ORG

Give Me Back My Monolith

“It feels like we’re starting to pass the peak of the hype cycle of microservices.” Interesting counterpoint to the “everything should be broken down into microservices” hypetrain. Not Python-specific, but worth a read nonetheless.
CRAIG KERSTIENS opinion

Discussions

Guido Explains Why Python Uses 0-Based Indexing

Google Plus is shutting down soon, so here’s a final hurrah.
GOOGLE.COM

There Are Some Huge Speedups in Python 3.8. Will They Also Be Put Into the Older Versions?

REDDIT

Python Jobs

alt

Brought to you by Indeed Prime

sponsor

Apply today to see what job opportunities are waiting for you!

Machine Learning and Data Science Developer (Austin, TX)

Protection Engineering Consultants LLC

Lead Python Developer (Toronto, Canada)

Kognitiv

Senior Systems Engineer (Hamilton, Canada)

Preteckt

Python Software Engineer (Berlin, Germany)

Wooga

Computer Science Teacher (Pasadena, CA)

ArtCenter College of Design

Senior Python Engineer (New York, NY)

15Five

More Python Jobs >>>

Articles & Tutorials

Understanding the Python Mock Object Library

In this tutorial, you’ll learn how to use the Python mock object library, unittest.mock, to create and use mock objects to improve your tests. Obstacles like complex logic and unpredictable dependencies make writing valuable tests difficult, but unittest.mock can help you overcome these obstacles.
REAL PYTHON

How I Translated a Mathematical Algorithm Into Code: TF-IDF to Python

Does your brain short-circuit when you see a mathematical algorithm? Don’t worry, you’re not alone. In this post you’ll see how the author worked her way through an algorithm, namely TF-IDF, and got it up and running in Python. Nice writeup!
SILKE HENDERICKX • Shared by Silke Henderickx

Take ActiveState’s ~7 Min Survey for a Chance to Win a Lego Star Wars TIE Fighter

alt

We want to know your pain points building & programming open source languages. We’ve got 3 cool prizes too. Click to speed through this ~7min survey →
ACTIVESTATE sponsor

10 Python Image Manipulation Tools

Nice overview of Python libraries that provide an easy and intuitive way to transform images and make sense of the underlying data.
PARUL PANDEY

Tips and Tricks to Write LaTeX Papers in With Figures Generated in Python

Some nice tips and example code for writing scientific papers in LaTeX, with figures generated in Python.
VINCENT ETTER

Make Python Delete Your Unwanted Emails Periodically

How to use the Gmail API to create a Python script which will automatically search & delete the messages matching your query.
UDIT VASHISHT • Shared by Udit Vashisht

Python’s except Quirk

I don’t know how Alex comes up with these, but that’s a fun one :)
ALEX BECKER

How to Distribute a wxPython Application

You finished up a wonderful GUI application using wxPython. How do you share it with the world? Read Mike’s article to find out.
MIKE DRISCOLL

Django: An Unofficial Opinionated FAQ

KRISTIAN GLASS

Python Standard Library Gems: collections.Counter

IVAN SAGALAEV

How to Use Grouping Sets in Django

“How we cut a heavy admin dashboard response time in half with advanced SQL and some Django hackery.”
HAKI BENITA

Projects & Code

OWASP/CheatSheetSeries: High Value Information on Specific Application Security Topics

GITHUB.COM/OWASP

orm: An Async ORM

GITHUB.COM/ENCODE

namedzip: Extends zip() and itertools.zip_longest() to Generate Named Tuples

GITHUB.COM/ERBERLIN

transistor: A Python Web Scraping Framework for Structured Web Pages

GITHUB.COM/BOMQUOTE

instaviz: Instant Visualization of Python AST and Code Objects

ANTHONY SHAW

Events

PyData Bristol Meetup

March 21, 2019
MEETUP.COM

Python Northwest

March 21, 2019
PYNW.ORG.UK

PyLadies Dublin

March 21, 2019
PYLADIES.COM

IndyPy Automate Conf 2019

March 22 to March 23, 2019
INDYPY.ORG

PyCon SK 2019

March 22 to March 25, 2019
PYCON.SK

Inland Empire Pyladies (CA, USA)

March 25, 2019
MEETUP.COM


Happy Pythoning!
This was PyCoder’s Weekly Issue #360.
View in Browser »

alt

[ Subscribe to 🐍 PyCoder’s Weekly 💌 – Get the best Python news, articles, and tutorials delivered to your inbox once a week >> Click here to learn more ]

March 19, 2019 07:30 PM UTC


Mike Driscoll

How to Distribute a wxPython Application

Let’s say you finished up a wonderful GUI application using wxPython. How do you share it with the world? This is always the dilemma when you finish an amazing program. Fortunately, there are several ways you can share your code. If you want to share your code with other developers, than Github or a similar website is definitely a good way to do. I won’t be covering using Git or Mercurial here. Instead what you will learn here is how to turn your application into an executable.

By turning your code into an executable, you can allow a user to just download the binary and run it without requiring them to download Python, your source code and your dependencies. All of those things will be bundled up into the executable instead.

There are many tools you can use to generate an executable:

You will be using PyInstaller in this tutorial. The main benefit to using PyInstaller is that it can generate executables for Windows, Mac and Linux. Note that it does not support cross-compiling. What that means is that you cannot run PyInstaller on Linux to create a Windows executable. Instead, PyInstaller will only create an executable for the OS that it is ran on. In other words, if you run PyInstaller on Windows, it will create a Windows executable only.


Installing PyInstaller

Installing the PyInstaller package is nice and straightforward. All you need is pip.

Here is how you would install PyInstaller to your system Python:

pip install pyinstaller

You could also install PyInstaller to a virtual Python environment using Python’s venv module or the virtualenv package.


Generating an Executable

The nice thing about PyInstaller is that it is very easy to use out of the box. All you need to do is run the `pyinstaller` command followed by the path to the main file of the application that you want to convert to an executable.

Here is a non-working example:

pyinstaller path/to/main/script.py

If the PyInstaller application is not found, you may have to specify a full path to it. By default, PyInstaller installs to Python’s **Scripts** sub-folder, which is going to be in your system Python folder or in your virtual environment.

Let’s take one of the simple applications from my upcoming book and turn it into an executable. For example, you could use image_viewer_slideshow.py from chapter 3:

# image_viewer_slideshow.py
 
import glob
import os
import wx
 
class ImagePanel(wx.Panel):
 
    def __init__(self, parent):
        super().__init__(parent)
        self.max_size = 240
        self.photos = []
        self.current_photo = 0
        self.total_photos = 0
        self.layout()
 
        self.slideshow_timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.on_next, self.slideshow_timer)
 
    def layout(self):
        """
        Layout the widgets on the panel
        """
 
        self.main_sizer = wx.BoxSizer(wx.VERTICAL)
        btn_sizer = wx.BoxSizer(wx.HORIZONTAL)
 
        img = wx.Image(self.max_size, self.max_size)
        self.image_ctrl = wx.StaticBitmap(self, wx.ID_ANY, 
                                             wx.Bitmap(img))
        self.main_sizer.Add(self.image_ctrl, 0, wx.ALL|wx.CENTER, 5)
        self.image_label = wx.StaticText(self, label="")
        self.main_sizer.Add(self.image_label, 0, wx.ALL|wx.CENTER, 5)
 
        btn_data = [("Previous", btn_sizer, self.on_previous),
                    ("Slide Show", btn_sizer, self.on_slideshow),
                    ("Next", btn_sizer, self.on_next)]
        for data in btn_data:
            label, sizer, handler = data
            self.btn_builder(label, sizer, handler)
 
        self.main_sizer.Add(btn_sizer, 0, wx.CENTER)
        self.SetSizer(self.main_sizer)
 
    def btn_builder(self, label, sizer, handler):
        """
        Builds a button, binds it to an event handler and adds it to a sizer
        """
        btn = wx.Button(self, label=label)
        btn.Bind(wx.EVT_BUTTON, handler)
        sizer.Add(btn, 0, wx.ALL|wx.CENTER, 5)
 
    def on_next(self, event):
        """
        Loads the next picture in the directory
        """
        if not self.photos:
            return
 
        if self.current_photo == self.total_photos - 1:
            self.current_photo = 0
        else:
            self.current_photo += 1
        self.update_photo(self.photos[self.current_photo])
 
    def on_previous(self, event):
        """
        Displays the previous picture in the directory
        """
        if not self.photos:
            return
 
        if self.current_photo == 0:
            self.current_photo = self.total_photos - 1
        else:
            self.current_photo -= 1
        self.update_photo(self.photos[self.current_photo])
 
    def on_slideshow(self, event):
        """
        Starts and stops the slideshow
        """
        btn = event.GetEventObject()
        label = btn.GetLabel()
        if label == "Slide Show":
            self.slideshow_timer.Start(3000)
            btn.SetLabel("Stop")
        else:
            self.slideshow_timer.Stop()
            btn.SetLabel("Slide Show")
 
    def update_photo(self, image):
        """
        Update the currently shown photo
        """
        img = wx.Image(image, wx.BITMAP_TYPE_ANY)
        # scale the image, preserving the aspect ratio
        W = img.GetWidth()
        H = img.GetHeight()
        if W > H:
            NewW = self.max_size
            NewH = self.max_size * H / W
        else:
            NewH = self.max_size
            NewW = self.max_size * W / H
        img = img.Scale(NewW, NewH)
 
        self.image_ctrl.SetBitmap(wx.Bitmap(img))
        self.Refresh()
 
    def reset(self):
        img = wx.Image(self.max_size,
                       self.max_size)
        bmp = wx.Bitmap(img)
        self.image_ctrl.SetBitmap(bmp)
        self.current_photo = 0
        self.photos = []
 
 
class MainFrame(wx.Frame):
 
    def __init__(self):
        super().__init__(None, title='Image Viewer',
                                        size=(400, 400))
        self.panel = ImagePanel(self)
        self.create_toolbar()
        self.Show()
 
    def create_toolbar(self):
        """
        Create a toolbar
        """
        self.toolbar = self.CreateToolBar()
        self.toolbar.SetToolBitmapSize((16,16))
 
        open_ico = wx.ArtProvider.GetBitmap(
            wx.ART_FILE_OPEN, wx.ART_TOOLBAR, (16,16))
        openTool = self.toolbar.AddTool(
            wx.ID_ANY, "Open", open_ico, "Open an Image Directory")
        self.Bind(wx.EVT_MENU, self.on_open_directory, openTool)
 
        self.toolbar.Realize()
 
    def on_open_directory(self, event):
        """
        Open a directory dialog
        """
        with wx.DirDialog(self, "Choose a directory",
                          style=wx.DD_DEFAULT_STYLE) as dlg:
 
            if dlg.ShowModal() == wx.ID_OK:
                self.folderPath = dlg.GetPath()
 
                photos = glob.glob(os.path.join(self.folderPath, '*.jpg'))
                self.panel.photos = photos
                if photos:
                    self.panel.update_photo(photos[0])
                    self.panel.total_photos = len(photos)
                else:
                    self.panel.reset()
 
 
if __name__ == '__main__':
    app = wx.App(redirect=False)
    frame = MainFrame()
    app.MainLoop()

If you wanted to turn it into an executable, you would run the following:

pyinstaller image_viewer_slideshow.py

Make sure that when you run this command, your current working directory is the one that contains the script you are converting to an executable. PyInstaller will be creating its output in whatever the current working directory is.

When you run this command, you should see something like this in your terminal:

PyInstaller will create two folders in the same folder as the script that you are converting called **dist** and **build**. The **dist** folder is where you will find your executable if PyInstaller completes successfully. There will be many other files in the **dist** folder besides your executable. These are files that are required for your executable to run.

Now let’s try running your newly created executable. When I ran my copy, I noticed that a terminal / console was appearing behind my application.

Image Viewer with Console in Background

This is normal as the default behavior of PyInstaller is to build your application as if it were a command-line application, not a GUI.

You will need to add the –noconsole flag to remove the console:

pyinstaller image_viewer_slideshow.py --noconsole

Now when you run the result, you should no longer see a console window appearing behind your application.

It can be complicated to distribute lots of files, so PyInstaller has another command that you can use to bundle everything up into a single executable. That command is `–onefile`. As an aside, a lot of the commands that you use with PyInstaller have shorter aliases. For example, there is a shorter alias for `–noconsole` that you can also use called: -w. Note the single dash in `-w`.

So let’s take that information and have PyInstaller create a single file executable with no console:

[python] pyinstaller image_viewer_slideshow.py --onefile -w

You should now have just one file in the dist folder.


The spec file

PyInstaller has the concept of specification files. They are kind of like a setup.py script, which is something that you use with Python’s distutils. These spec files tell PyInstaller how to build your executable. PyInstaller will generate one for you automatically with the same name as the passed in script, but with a .spec extension. So if you passed in image_viewer_slideshow.py, then you should see a image_viewer_slideshow.spec file after running PyInstaller. This spec file will be created in the same location as your application file.

Here is the contents of the spec file that was created from the last run of PyInstaller above:

# -*- mode: python -*-
 
block_cipher = None
 
 
a = Analysis(['image_viewer.py'],
             pathex=['C:\\Users\\mdriscoll\\Documents\\test'],
             binaries=[],
             datas=[],
             hiddenimports=[],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher,
             noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)
exe = EXE(pyz,
          a.scripts,
          a.binaries,
          a.zipfiles,
          a.datas,
          [],
          name='image_viewer',
          debug=False,
          bootloader_ignore_signals=False,
          strip=False,
          upx=True,
          runtime_tmpdir=None,
          console=False )

While PyInstaller worked fine with the image viewer example, you may find that it won’t work out of the box if you had other dependencies, such as NumPy or Pandas. If you run into issues with PyInstaller, it has very verbose logs that you can use to help you figure out the issue. One good location is the `build/cli/warn-cli.txt` file. You may also want to rebuild without the `-w` command so that you can see what is being printed to stdout in the console window.

There are also options for changing the log level during building that may help you uncover issues.

If none of those work, try Google or go to PyInstaller’s support page and get help there.


Creating Executables for Mac

While the same commands should work on Mac OSX as it does on Windows, I found that I needed to run the following command to generate a working executable:

pyinstaller image_viewer_slideshow.py --windowed

The output that PyInstaller generates will be slightly different and the result is an application file.

Another popular option for generating applications on Mac is a Python package called py2app.


Creating Executables for Linux

For Linux, it is usually recommended that you build the executable with an old version of glibc because the newer glibc versions are backwards compatible. By building with an old version of Linux, you can usually target a wider variety of Linux versions. But your mileage may vary.

After the files are generated, you can just tar them up into a gzipped tarball (.tax.gz). You could even using the archiving application you created in this book to do that for you, if you wanted.

An alternative would be to learn how to create a .deb or related file that most Linux versions can install.


Learning More About PyInstaller

This article is not meant to be an in-depth guide to PyInstaller. It will likely change much faster than wxPython, so it is recommended that you read the documentation for PyInstaller instead. It will always be the most up-to-date location to get the information you need on the project.


What About Installers?

Windows users know that most of the time you have an installer application that you can run to install your application on your computer and put some shortcuts here and there. There are several useful free programs that you can use to create a Windows Installer as well as some paid ones

Here are the two freeware applications I see mentioned the most:

I have used Inno Setup to create a Windows installer on several occasions. It is easy to use and requires only a little reading of its documentation to get it working. I haven’t used NSIS before, but I suspect it is quite easy to use as well.

Let’s use Inno Setup as an example and see how to generate an installer with it.


Creating an Installer with Inno Setup

Inno Setup is a nice freeware application that you can use to create professional looking installer programs. It works on most versions of Windows. I personally have used it for quite a few years. While Inno Setup is not open source, it is still a really nice program. You will need to download and install it from there website.

Once installed, you can use this tool to create an installer for the executable you created earlier in this chapter.

To get started, just run Inno Setup and you should see the following:

Inno Setup’s Startup Page

While Inno Setup defaults to opening an existing file, what you want to do is choose the second option from the top: “Create a new script file using the Script Wizard”. Then press **OK**.

You should now see the first page of the Inno Setup Script Wizard. Just hit **Next** here since there’s nothing else you can really do.

Now you should see something like this:

Inno Setup Script Wizard Application Information Page

This is where you enter your applications name, its version information, the publisher’s name and the application’s website. I pre-filled it with some examples, but you can enter whatever you want to here.

Go ahead and press Next and you should see page 3:

Inno Setup Script Wizard Application Folder Page

This page of the wizard is where you can set the application’s install directory. On Windows, most applications install to **Program Files**, which is also the default here. This is also where you set the folder name for your application. This is the name of the folder that will appear in Program Files. Alternatively, you can check the box at the bottom that indicates that your application doesn’t need a folder at all.

Let’s go to the next page:

Inno Setup Script Wizard Application Files Page

Here is where you will choose the main executable file. In this case, you want to choose the executable you created with PyInstaller. If you didn’t create the executable using the –onefile flag, then you can add the other files using the Add file(s)… button. If your application requires any other special files, like a SQLite database file or images, this is also where you would want to add them.

By default, this page will allow the user to run your application when the installer finishes. A lot of installers do this, so it’s actually expected by most users.

Let’s continue:

Inno Setup Script Wizard Application Shortcuts Page

This is the Application Shortcuts page and it allows you to manage what shortcuts are created for your application and where they should go. The options are pretty self-explanatory. I usually just use the defaults, but you are welcome to change them however you see fit.

Let’s find out what’s on the documentation page:

Inno Setup Script Wizard Application Documentation Page

The Documentation Page of the wizard is where you can add your application’s license file. For example, if you were putting out an open source application, you can add the GPL or MIT or whatever license file you need there. If this were a commercial application, this is where you would add your End-Users License Agreement (EULA) file.

Let’s see what’s next:

Inno Setup Script Wizard Setup Languages Page

Here you can set up which setup languages should be included. Inno Setup supports quite a few languages, with English as the default choice.

Now let’s find out what compiler settings are:

Inno Setup Script Wizard Compiler Settings Page

The Compiler Settings page let’s you name the output setup file, which defaults to simply **setup**. You can set the output folder here, add a custom setup file icon and even add password protection to the setup file. I usually just leave the defaults alone, but this is an opportunity to add some branding to the setup if you have a nice icon file handy.

The next page is for the preprocessor:

Inno Setup Script Wizard Preprocessor Page

The preprocessor is primarily for catching typos in the Inno Setup script file. It basically adds some helpful options at compile time to your Inno Setup script.

Check out the documentation for full details.

Click Next and you should see the last page of the wizard:

Inno Setup Script Wizard End Page

Click Finish and Inno Setup will generate an Inno Setup Script (.iss) file. When it is finished, it will ask you if you would like to compile the file.

Go ahead and accept that dialog and you should see the following:

Inno Setup Script

This is the Inno Setup Script editor with your newly generated script pre-loaded into it. The top half is the script that was generated and the bottom half shows the compiler’s output. In this screenshot, it shows that the setup file was generated successfully but it also displays a warning that you might want to rename the setup file.

At this point, you should have a working installer executable that will install your program and any files it depends on to the right locations. It will also create shortcuts in the Windows Start menu and whichever other locations you specified in the wizard.

The script file itself can be edited. It is just a text file and the syntax is well documented on Inno Setup’s website.


Code Signing

Windows and Mac OSX prefer that applications are signed by a corporation or the developer. Otherwise you will see a warning that you are using an unsigned piece of code or software. The reason this matters is that it protects your application from being modified by someone else. You can think of code signing as a kind of embedded MD5 hash in your application. A signed application can be traced back to whomever signed it, which makes it more trust-worthy.

If you want to sign code on Mac OSX, you can use XCode

Windows has several options for signing their code. Here is a URL for getting your application certified for Windows

You can also purchase a certificate from various companies that specialize in code signing, such as digicert.

There is also the concept of self-signed certificates, but that is not for production or for end users. You would only self-sign for internal testing, proof-of-concept, etc. You can look up how to do that on your own.


Wrapping Up

You have now learned how to generate executables using PyInstaller on Windows, Mac and Linux. The command to generate the executable is the same across all platforms. While you cannot create a Windows executable by running PyInstaller on Linux, it is still quite useful for creating executable for the target operating system.

You also learned how to use Inno Setup to create an installer for Windows. You can now use these skills to create executables for your own applications or for some of the other applications that you created in this book!


Further Reading

March 19, 2019 05:15 PM UTC


Django Weblog

2018 Malcolm Tredinnick Memorial Prize awarded to Kojo Idrissa

The Board of the Django Software Foundation is pleased to announce that the 2018 Malcolm Tredinnick Memorial Prize has been awarded to Kojo Idrissa.

Kojo has been active in the Django community since at least 2015, if not earlier. He's been a DjangoCon US organizer since 2016, former DEFNA board member, and current DEFNA North American Ambassador.

Kojo has hosted an orientation for first-time DjangoCon US attendees for the last several years, which could not be a better example of Malcolm's friendly spirit to new users.

Ken Whitesell, who nominated Kojo, also noted many Kojo's other contributions:

Kojo is a very active member of the weekly CodeNewbie chats. Hosts the DjangoCon new-user orientation session. Very visible presence at DjangoCon, always seems to be focused on ensuring first time attendees have the best possible experience.

The other nominees this year were:

Every year we receive many nominations and it's always hard to pick the winner. In fact, some have been nominated in multiple years. Malcolm would be very proud of the legacy he has fostered in our community!

Congratulations Kojo on the well deserved honor!

March 19, 2019 04:04 PM UTC


Real Python

Python Decorators 101

In this course on Python decorators, you’ll learn what they are and how to create and use them. Decorators provide a simple syntax for calling higher-order functions in Python. By definition, a decorator is a function that takes another function and extends the behavior of the latter function without explicitly modifying it.


[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short & sweet Python Trick delivered to your inbox every couple of days. >> Click here to learn more and see examples ]

March 19, 2019 02:00 PM UTC


Shyama Sankar Vellore

Python Tuples: Cheat Sheet

A cheat sheet for tuples in Python. What are tuples? How are they used in Python?

March 19, 2019 06:56 AM UTC


leftmouseclickin

Plotting the average directional movement index rating line with python

Our Own Score

In this chapter, we will create the plot adxr method in the ongoing Forex and Stock application project to plot the average directional movement index rating line. The Average Directional Movement Index Rating (ADXR) measures the strength of the Average Directional Movement Index (ADX). It’s calculated by taking the average of the current ADX and the ADX from one time period before (time periods can vary, but the most typical period used is 14 days).

Below is the modified version of the program. We have included a new plot adxr method as well as the plot adxr button which will be used to call the plot adxr method.

import json
from tkinter import *
import tkinter.ttk as tk
from alpha_vantage.foreignexchange import ForeignExchange
from alpha_vantage.techindicators import TechIndicators
from alpha_vantage.timeseries import TimeSeries
import matplotlib.pyplot as plt
from alpha_vantage.sectorperformance import SectorPerformances

win = Tk() # Create tk instance
win.title("Real Forex n Stock") # Add a title
win.resizable(0, 0) # Disable resizing the GUI
win.configure(background='white') # change window background color

selectorFrame = Frame(win, background="white") # create the top frame to hold base and quote currency combobox
selectorFrame.pack(anchor = "nw", pady = 2, padx=10)
currency_label = Label(selectorFrame, text = "Select base currency / quote currency :", background="white")
currency_label.pack(anchor="w") # the currency pair label

selector1Frame = Frame(win, background="white") # create the middle frame to hold base and quote currency combobox
selector1Frame.pack(anchor = "nw", pady = 2, padx=10)
stock_label = Label(selector1Frame, text = "Select Stock / Time Interval / Series type / Moving average type / Fast Period / Slow Period :", background="white")
stock_label.pack(anchor="w") # the stock label

curr1 = tuple() # the tuple which will be populated by base and quote currency
currency_list = ['AUD', 'BCH', 'BNB', 'BND', 'BTC', 'CAD', 'CHF', 'CNY', 'EOS', 'EUR', 'ETH', 'GBP', 'HKD', 'JPY', 'LTC', 'NZD', 'MYR', 'TRX', 'USD', 'USDT', 'XLM', 'XRP'] # major world currency pairs

# populate the combo box for both the base and quote currency
for key in currency_list:
    curr1 += (key, )

# populate the stock symbol tuple
f = open("stock.txt", "r")
curr2 = tuple()
for line in f.readlines():
    curr2 += (line.replace('\n', ''),)
f.close()

# Create a combo box for base currency
base_currency = StringVar() # create a string variable
based = tk.Combobox(selectorFrame, textvariable=base_currency)
based['values'] = curr1
based.pack(side = LEFT, padx=3)

# Create a combo box for quote currency
quote_currency = StringVar() # create a string variable
quote = tk.Combobox(selectorFrame, textvariable=quote_currency)
quote['values'] = curr1
quote.pack(side = LEFT, padx=3)

# Create a combo box for stock items
stock_symbol = StringVar() # create a string variable
stock = tk.Combobox(selector1Frame, textvariable=stock_symbol)
stock['values'] = curr2
stock.current(0)
stock.pack(side = LEFT, padx=3)

interval = tk.Combobox(selector1Frame)
interval['values'] = ('1min', '5min', '15min', '30min', '60min', 'daily', 'weekly', 'monthly')
interval.current(0)
interval.pack(side = LEFT, padx=3)

price_type = tk.Combobox(selector1Frame)
price_type['values'] = ('close', 'open', 'high', 'low')
price_type.current(0)
price_type.pack(side =LEFT, padx=3)

matype_type = tk.Combobox(selector1Frame, width=37)
matype_type['values'] = ('Simple Moving Average (SMA)', 'Exponential Moving Average (EMA)', 'Weighted Moving Average (WMA)', 'Double Exponential Moving Average (DEMA', 'Triple Exponential Moving Average (TEMA)', 'Triangular Moving Average (TRIMA', 'T3 Moving Average', 'Kaufman Adaptive Moving Average (KAMA)', ' MESA Adaptive Moving Average (MAMA)')
matype_type.current(0)
matype_type.pack(side =LEFT, padx=3)
mattype_list = ['Simple Moving Average (SMA)', 'Exponential Moving Average (EMA)', 'Weighted Moving Average (WMA)', 'Double Exponential Moving Average (DEMA', 'Triple Exponential Moving Average (TEMA)', 'Triangular Moving Average (TRIMA', 'T3 Moving Average', 'Kaufman Adaptive Moving Average (KAMA)', ' MESA Adaptive Moving Average (MAMA)']

# fill up the fast period and slow period combo boxes with integer ranging from 2 to 10,000
fa = tuple()
for i in range(2, 10001):
    fa += (i, )

fast_pe = tk.Combobox(selector1Frame)
fast_pe['values'] = fa
fast_pe.current(0)
fast_pe.pack(side=LEFT, padx=3)

slow_pe = tk.Combobox(selector1Frame)
slow_pe['values'] = fa
slow_pe.current(0)
slow_pe.pack(side=LEFT, padx=3)

# create text widget area
s = StringVar() # create string variable which will be used to fill up the Forex or stock data
# create currency frame and text widget to display the incoming forex data
currencyFrame = Frame(win)
currencyFrame.pack(side=TOP, fill=X)
currency = Label(currencyFrame)
currency.pack(fill=X)
text_widget = Text(currency, fg='white', background='black')
text_widget.pack(fill=X)
s.set("Click the find button to find out the currency exchange rate")
text_widget.insert(END, s.get())

buttonFrame = Frame(win) # create a bottom frame to hold the find button
buttonFrame.pack(side = BOTTOM, fill=X, pady = 6, padx=10)

# first get the api key and secret from the file
f = open("alpha.txt", "r")
api_key = f.readline()
f.close()
api_key = api_key.replace('\n', '')

def get_exchange_rate(): # this method will display the incoming forex data after the api called

    try:
        cc = ForeignExchange(key= api_key)
        from_ = based.get()
        to_ = quote.get()

        countVar = StringVar()  # use to hold the character count
        text_widget.tag_remove("search", "1.0", "end")  # cleared the hightlighted currency pair

        if(from_ != '' and to_ != '' and from_ != to_):
            data, _ = cc.get_currency_exchange_rate(from_currency=from_, to_currency=to_)
            exchange_rate = dict(json.loads(json.dumps(data)))
            count = 1
            sell_buy = str(count) + ".) Pair : " + exchange_rate['1. From_Currency Code'] + "(" + exchange_rate['2. From_Currency Name'] + ")" + " / " + exchange_rate['3. To_Currency Code']+"(" + exchange_rate['4. To_Currency Name'] + ") : "  + str(exchange_rate['5. Exchange Rate']) + '\n'
            text_widget.delete('1.0', END)  # clear all those previous text first
            s.set(sell_buy)
            text_widget.insert(INSERT, s.get())  # display forex rate in text widget
            pos = text_widget.search(from_, "1.0", stopindex="end", count=countVar)
            text_widget.tag_configure("search", background="green")
            end_pos = float(pos) + float(0.7)
            text_widget.tag_add("search", pos, str(end_pos))  # highlight the background of the searched currency pair
            pos = float(pos) + 2.0
            text_widget.see(str(pos))

    except:
        print("An exception occurred")

def plot_stock_echange():

    try:
        stock_symbol_text = stock.get() # get the selected symbol
        if(stock_symbol_text!= ''):
            ts = TimeSeries(key=api_key, output_format='pandas')
            data, meta_data = ts.get_intraday(symbol=stock_symbol_text, interval='1min', outputsize='full')
            data['4. close'].plot()
            stock_title = 'Intraday Times Series for the ' + stock_symbol_text + ' stock (1 min)'
            plt.title(stock_title)
            plt.show()
    except:
        print("An exception occurred")

def plot_stock_technical():

    try:
        stock_symbol_text = stock.get() # get the selected stock symbol
        if(stock_symbol_text!= ''):

            ti = TechIndicators(key=api_key, output_format='pandas')
            data, meta_data = ti.get_bbands(symbol=stock_symbol_text, interval=interval.get(), series_type=price_type.get(), matype=mattype_list.index(matype_type.get()), time_period=int(interval.get().replace('min', '')))
            data.plot()
            stock_title = 'BBbands indicator for ' + stock_symbol_text + ' ' + interval.get()
            plt.title(stock_title)
            plt.show()
    except:
        print("An exception occurred")

def plot_op(): # plot the Absolute price oscillator (APO)

    try:
        stock_symbol_text = stock.get() # get the selected stock symbol
        if(stock_symbol_text!= ''):

            ti = TechIndicators(key=api_key, output_format='pandas')
            data, meta_data = ti.get_apo(symbol=stock_symbol_text, interval=interval.get(), series_type=price_type.get(), matype=mattype_list.index(matype_type.get()), fastperiod = fast_pe.get(), slowperiod= slow_pe.get())
            data.plot()
            stock_title = 'Absolute Price Oscillator (APO) for ' + stock_symbol_text + ' ' + interval.get()
            plt.title(stock_title)
            plt.show()
    except ValueError:
        print("An exception occurred")

def plot_adxr(): # plot the average directional movement index rating

    try:
        stock_symbol_text = stock.get() # get the selected stock symbol
        if(stock_symbol_text!= ''):

            ti = TechIndicators(key=api_key, output_format='pandas')
            data, meta_data = ti.get_adxr(symbol=stock_symbol_text, interval=interval.get(), time_period=int(interval.get().replace('min', '')))
            data.plot()
            stock_title = 'Average directional movement index rating for ' + stock_symbol_text + ' at ' + interval.get()
            plt.title(stock_title)
            plt.show()
    except ValueError:
        print("An exception occurred")

def plot_sector_performance():

    sp = SectorPerformances(key=api_key, output_format='pandas')
    data, meta_data = sp.get_sector()
    data['Rank A: Real-Time Performance'].plot(kind='bar')
    plt.title('Real Time Performance (%) per Sector')
    plt.tight_layout()
    plt.grid()
    plt.show()

def plot_ad():

    try:
        stock_symbol_text = stock.get()  # get the selected stock symbol
        if (stock_symbol_text != ''):
            ti = TechIndicators(key=api_key, output_format='pandas')
            data, meta_data = ti.get_ad(symbol=stock_symbol_text, interval=interval.get())
            data.plot()
            stock_title = 'Chaikin A/D line values for ' + stock_symbol_text + ' ' + interval.get()
            plt.title(stock_title)
            plt.show()
    except:
        print("An exception occurred")

action_vid = tk.Button(buttonFrame, text="Calculate Exchange Rate", command=get_exchange_rate) # button used to find out the exchange rate of currency pair
action_vid.pack(side=LEFT, padx=2)
action_stock_plot = tk.Button(buttonFrame, text="Plot Stock", command=plot_stock_echange) # button used to plot the intra-minute stock value
action_stock_plot.pack(side=LEFT, padx=2)
action_technical_plot = tk.Button(buttonFrame, text="Plot Technical", command=plot_stock_technical) # button used to plot the 60 minutes stock technical value
action_technical_plot.pack(side=LEFT, padx=2)
action_sector_plot = tk.Button(buttonFrame, text="Plot Sector Performance", command=plot_sector_performance) # button used to plot the sector performance graph
action_sector_plot.pack(side=LEFT, padx=2)
action_ad_plot = tk.Button(buttonFrame, text="Plot AD Line", command=plot_ad) # button used to plot the A/D line graph
action_ad_plot.pack(side=LEFT, padx=2)
action_ad_op = tk.Button(buttonFrame, text="Plot APO Line", command=plot_op) # button used to plot the APO line graph
action_ad_op.pack(side=LEFT, padx=3)
action_adxr = tk.Button(buttonFrame, text="Plot ADXR Line", command=plot_adxr) # button used to plot the average directional movement index rating
action_adxr.pack(side=LEFT, padx=3)
win.iconbitmap(r'ico.ico')
win.mainloop()

As usual run the program and then click on the plot adxr button we will see this outcome.

March 19, 2019 04:12 AM UTC


codingdirectional

Get only the latest live match from NBA with python

Hello and welcome back, in this chapter we will continue to develop the previous sports score application by showing all the latest live matches from the NBA on the text widget area. The sports.py module does not have a method to only return the live NBA matches but instead that API call will return basically all the live basketball matches from all the basketball leagues around the world. Therefore we will need to filter out all those none NBA results before showing the data on the text widget. Below is the modified version of the program which will do just that. We will perform the filtering process under the get matches method.

import sports
import json
from tkinter import *
import tkinter.ttk as tk
import datetime

win = Tk() # Create tk instance
win.title("NBA") # Add a title
win.resizable(0, 0) # Disable resizing the GUI
win.configure(background='white') # change window background color

selectorFrame = Frame(win, background="white") # create top frame to hold team 1 vs team 2 combobox
selectorFrame.pack(anchor = "nw", pady = 2, padx=10)
match_label = Label(selectorFrame, text = "Select Team 1 vs Team 2 :", background="white")
match_label.pack(anchor="w") # the team label

# Create a combo box for team 1
team1 = tk.Combobox(selectorFrame)
team1.pack(side = LEFT, padx=3)

# Create a combo box for team 2
team2 = tk.Combobox(selectorFrame)
team2.pack(side = LEFT, padx=3)

s = StringVar() # create string variable
# create match frame and text widget to display the incoming match data
matchFrame = Frame(win)
matchFrame.pack(side=TOP)
match = Label(matchFrame)
match.pack()
text_widget = Text(match, fg='white', background='black')
text_widget.pack()
s.set("Click below buttons to find out the match result")
text_widget.insert(END, s.get())

buttonFrame = Frame(win) # create a bottom frame to hold the find button
buttonFrame.pack(side = BOTTOM, fill=X, pady = 6)

# fill up the combo boxes with the team name data from the text file
team_tuple = tuple()
f = open("TextFile1.txt", "r")
nba_list = [] # will be used to filter out the unwanted team from the other league
for line in f.readlines():
    line = line.replace('\n', '')
    nba_list.append(line)
    team_tuple += (line, )
f.close()

team1["values"] = team_tuple
team1.current(1)
team2["values"] = team_tuple
team2.current(0)

def get_matches(): # show all the NBA team matches

    match_str = '               Live NBA Matches ' + str(datetime.datetime.now()) + '\n'

    try:
        matches = sports.get_sport(sports.BASKETBALL)
        for item in matches:
            match_all = str(item)
            for nba_team in nba_list:
                if(nba_team in match_all):
                    match_str += (match_all)  + '\n'
                    break
        text_widget.delete('1.0', END) # clear all those previous text first
        s.set(match_str)
        text_widget.insert(INSERT, s.get()) # display teams match data in text widget
    except:
        print("An exception occurred")

def get_match(): # return the recent match of team 1 vs team 2
   
    try:
        match = sports.get_match(sports.BASKETBALL, team1.get(), team2.get())
        text_widget.delete('1.0', END) # clear all those previous text first
        s.set(match)
        text_widget.insert(INSERT, s.get()) # display team match data in text widget
    except:
        print("An exception occurred")

action_vid = tk.Button(buttonFrame, text="Latest Match", command=get_match) # button used to find out the team match data
action_vid.pack(side=LEFT, padx=2)
action_vid1 = tk.Button(buttonFrame, text="All Matches", command=get_matches) # button used to find out the teams match data
action_vid1.pack(side=LEFT, padx=2)

win.mainloop()

If you start the software and click on the All Matches button you will see all the live matches from NBA in the text widget area. Like, share or follow me on Twitter.

Download mine latest Free Firefox Extension on Firefox Store to show your love for my project.

Due to the tight daily schedule, this site will switch to twice a week updating starting from today onward.

March 19, 2019 03:23 AM UTC

March 18, 2019


Python Insider

Python 3.4.10 is now available

Python 3.4.10 is now available.  You can download it here.

Python 3.4.10 is the final release in the Python 3.4 series.  As of this release, the 3.4 branch has been retired, no further changes to 3.4 will be accepted, and no new releases will be made.  This is standard Python policy; Python releases get five years of support and are then retired.

If you're still using Python 3.4, you should consider upgrading to the current version--3.7.2 as of this writing.  Newer versions of Python have many new features, performance improvements, and bug fixes, which should all serve to enhance your Python programming experience.

We in the Python core development community thank you for your interest in 3.4, and we wish you all the best!

March 18, 2019 04:37 PM UTC

Python 3.5.7 is now available

Python 3.5.7 is now available.  You can download Python 3.5.7 here.

March 18, 2019 04:36 PM UTC


leftmouseclickin

Plotting Absolute Price Oscillator (APO) Line with Python

Our Own Score

If you make a search on Google about APO Line, this is what you will see: Absolute Price Oscillator (APO) moving averages of a security’s price and is expressed as an absolute value. APO crossing above zero is considered bullish while crossing below zero is bearish.

This is the line we are going to plot with the help of the alpha vantage module. Below is the edit version of the Forex and Stock application. The new plot op method will plot the APO line after we have clicked on the Plot APO Line button. Just like the BBbands indicator line we can include various parameters in the get_apo method.

import json
from tkinter import *
import tkinter.ttk as tk
from alpha_vantage.foreignexchange import ForeignExchange
from alpha_vantage.techindicators import TechIndicators
from alpha_vantage.timeseries import TimeSeries
import matplotlib.pyplot as plt
from alpha_vantage.sectorperformance import SectorPerformances

win = Tk() # Create tk instance
win.title("Real Forex n Stock") # Add a title
win.resizable(0, 0) # Disable resizing the GUI
win.configure(background='white') # change window background color

selectorFrame = Frame(win, background="white") # create the top frame to hold base and quote currency combobox
selectorFrame.pack(anchor = "nw", pady = 2, padx=10)
currency_label = Label(selectorFrame, text = "Select base currency / quote currency :", background="white")
currency_label.pack(anchor="w") # the currency pair label

selector1Frame = Frame(win, background="white") # create the middle frame to hold base and quote currency combobox
selector1Frame.pack(anchor = "nw", pady = 2, padx=10)
stock_label = Label(selector1Frame, text = "Select Stock / Time Interval / Series type / Moving average type / Fast Period / Slow Period :", background="white")
stock_label.pack(anchor="w") # the stock label

curr1 = tuple() # the tuple which will be populated by base and quote currency
currency_list = ['AUD', 'BCH', 'BNB', 'BND', 'BTC', 'CAD', 'CHF', 'CNY', 'EOS', 'EUR', 'ETH', 'GBP', 'HKD', 'JPY', 'LTC', 'NZD', 'MYR', 'TRX', 'USD', 'USDT', 'XLM', 'XRP'] # major world currency pairs

# populate the combo box for both the base and quote currency
for key in currency_list:
    curr1 += (key, )

# populate the stock symbol tuple
f = open("stock.txt", "r")
curr2 = tuple()
for line in f.readlines():
    curr2 += (line.replace('\n', ''),)
f.close()

# Create a combo box for base currency
base_currency = StringVar() # create a string variable
based = tk.Combobox(selectorFrame, textvariable=base_currency)
based['values'] = curr1
based.pack(side = LEFT, padx=3)

# Create a combo box for quote currency
quote_currency = StringVar() # create a string variable
quote = tk.Combobox(selectorFrame, textvariable=quote_currency)
quote['values'] = curr1
quote.pack(side = LEFT, padx=3)

# Create a combo box for stock items
stock_symbol = StringVar() # create a string variable
stock = tk.Combobox(selector1Frame, textvariable=stock_symbol)
stock['values'] = curr2
stock.current(0)
stock.pack(side = LEFT, padx=3)

interval = tk.Combobox(selector1Frame)
interval['values'] = ('1min', '5min', '15min', '30min', '60min', 'daily', 'weekly', 'monthly')
interval.current(0)
interval.pack(side = LEFT, padx=3)

price_type = tk.Combobox(selector1Frame)
price_type['values'] = ('close', 'open', 'high', 'low')
price_type.current(0)
price_type.pack(side =LEFT, padx=3)

matype_type = tk.Combobox(selector1Frame, width=37)
matype_type['values'] = ('Simple Moving Average (SMA)', 'Exponential Moving Average (EMA)', 'Weighted Moving Average (WMA)', 'Double Exponential Moving Average (DEMA', 'Triple Exponential Moving Average (TEMA)', 'Triangular Moving Average (TRIMA', 'T3 Moving Average', 'Kaufman Adaptive Moving Average (KAMA)', ' MESA Adaptive Moving Average (MAMA)')
matype_type.current(0)
matype_type.pack(side =LEFT, padx=3)
mattype_list = ['Simple Moving Average (SMA)', 'Exponential Moving Average (EMA)', 'Weighted Moving Average (WMA)', 'Double Exponential Moving Average (DEMA', 'Triple Exponential Moving Average (TEMA)', 'Triangular Moving Average (TRIMA', 'T3 Moving Average', 'Kaufman Adaptive Moving Average (KAMA)', ' MESA Adaptive Moving Average (MAMA)']

# fill up the fast period and slow period combo boxes with integer ranging from 2 to 10,000
fa = tuple()
for i in range(2, 10001):
    fa += (i, )

fast_pe = tk.Combobox(selector1Frame)
fast_pe['values'] = fa
fast_pe.current(0)
fast_pe.pack(side=LEFT, padx=3)

slow_pe = tk.Combobox(selector1Frame)
slow_pe['values'] = fa
slow_pe.current(0)
slow_pe.pack(side=LEFT, padx=3)

# create text widget area
s = StringVar() # create string variable which will be used to fill up the Forex data
# create currency frame and text widget to display the incoming forex data
currencyFrame = Frame(win)
currencyFrame.pack(side=TOP, fill=X)
currency = Label(currencyFrame)
currency.pack(fill=X)
text_widget = Text(currency, fg='white', background='black')
text_widget.pack(fill=X)
s.set("Click the find button to find out the currency exchange rate")
text_widget.insert(END, s.get())

buttonFrame = Frame(win) # create a bottom frame to hold the find button
buttonFrame.pack(side = BOTTOM, fill=X, pady = 6, padx=10)

# first get the api key and secret from the file
f = open("alpha.txt", "r")
api_key = f.readline()
f.close()
api_key = api_key.replace('\n', '')

def get_exchange_rate(): # this method will display the incoming forex data after the api called

    try:
        cc = ForeignExchange(key= api_key)
        from_ = based.get()
        to_ = quote.get()

        countVar = StringVar()  # use to hold the character count
        text_widget.tag_remove("search", "1.0", "end")  # cleared the hightlighted currency pair

        if(from_ != '' and to_ != '' and from_ != to_):
            data, _ = cc.get_currency_exchange_rate(from_currency=from_, to_currency=to_)
            exchange_rate = dict(json.loads(json.dumps(data)))
            count = 1
            sell_buy = str(count) + ".) Pair : " + exchange_rate['1. From_Currency Code'] + "(" + exchange_rate['2. From_Currency Name'] + ")" + " / " + exchange_rate['3. To_Currency Code']+"(" + exchange_rate['4. To_Currency Name'] + ") : "  + str(exchange_rate['5. Exchange Rate']) + '\n'
            text_widget.delete('1.0', END)  # clear all those previous text first
            s.set(sell_buy)
            text_widget.insert(INSERT, s.get())  # display forex rate in text widget
            pos = text_widget.search(from_, "1.0", stopindex="end", count=countVar)
            text_widget.tag_configure("search", background="green")
            end_pos = float(pos) + float(0.7)
            text_widget.tag_add("search", pos, str(end_pos))  # highlight the background of the searched currency pair
            pos = float(pos) + 2.0
            text_widget.see(str(pos))

    except:
        print("An exception occurred")

def plot_stock_echange():

    try:
        stock_symbol_text = stock.get() # get the selected symbol
        if(stock_symbol_text!= ''):
            ts = TimeSeries(key=api_key, output_format='pandas')
            data, meta_data = ts.get_intraday(symbol=stock_symbol_text, interval='1min', outputsize='full')
            data['4. close'].plot()
            stock_title = 'Intraday Times Series for the ' + stock_symbol_text + ' stock (1 min)'
            plt.title(stock_title)
            plt.show()
    except:
        print("An exception occurred")

def plot_stock_technical():

    try:
        stock_symbol_text = stock.get() # get the selected stock symbol
        if(stock_symbol_text!= ''):

            ti = TechIndicators(key=api_key, output_format='pandas')
            data, meta_data = ti.get_bbands(symbol=stock_symbol_text, interval=interval.get(), series_type=price_type.get(), matype=mattype_list.index(matype_type.get()), time_period=int(interval.get().replace('min', '')))
            data.plot()
            stock_title = 'BBbands indicator for ' + stock_symbol_text + ' ' + interval.get()
            plt.title(stock_title)
            plt.show()
    except:
        print("An exception occurred")

def plot_op(): # plot the Absolute price oscillator (APO)

    try:
        stock_symbol_text = stock.get() # get the selected stock symbol
        if(stock_symbol_text!= ''):

            ti = TechIndicators(key=api_key, output_format='pandas')
            data, meta_data = ti.get_apo(symbol=stock_symbol_text, interval=interval.get(), series_type=price_type.get(), matype=mattype_list.index(matype_type.get()), fastperiod = fast_pe.get(), slowperiod= slow_pe.get())
            data.plot()
            stock_title = 'Absolute Price Oscillator (APO) for ' + stock_symbol_text + ' ' + interval.get()
            plt.title(stock_title)
            plt.show()
    except ValueError:
        print("An exception occurred")

def plot_sector_performance():

    sp = SectorPerformances(key=api_key, output_format='pandas')
    data, meta_data = sp.get_sector()
    data['Rank A: Real-Time Performance'].plot(kind='bar')
    plt.title('Real Time Performance (%) per Sector')
    plt.tight_layout()
    plt.grid()
    plt.show()

def plot_ad():

    try:
        stock_symbol_text = stock.get()  # get the selected stock symbol
        if (stock_symbol_text != ''):
            ti = TechIndicators(key=api_key, output_format='pandas')
            data, meta_data = ti.get_ad(symbol=stock_symbol_text, interval=interval.get())
            data.plot()
            stock_title = 'Chaikin A/D line values for ' + stock_symbol_text + ' ' + interval.get()
            plt.title(stock_title)
            plt.show()
    except:
        print("An exception occurred")

action_vid = tk.Button(buttonFrame, text="Calculate Exchange Rate", command=get_exchange_rate) # button used to find out the exchange rate of currency pair
action_vid.pack(side=LEFT, padx=2)
action_stock_plot = tk.Button(buttonFrame, text="Plot Stock", command=plot_stock_echange) # button used to plot the intra-minute stock value
action_stock_plot.pack(side=LEFT, padx=2)
action_technical_plot = tk.Button(buttonFrame, text="Plot Technical", command=plot_stock_technical) # button used to plot the 60 minutes stock technical value
action_technical_plot.pack(side=LEFT, padx=2)
action_sector_plot = tk.Button(buttonFrame, text="Plot Sector Performance", command=plot_sector_performance) # button used to plot the sector performance graph
action_sector_plot.pack(side=LEFT, padx=2)
action_ad_plot = tk.Button(buttonFrame, text="Plot AD Line", command=plot_ad) # button used to plot the A/D line graph
action_ad_plot.pack(side=LEFT, padx=2)
action_ad_op = tk.Button(buttonFrame, text="Plot APO Line", command=plot_op) # button used to plot the APO line graph
action_ad_op.pack(side=LEFT, padx=3)

win.iconbitmap(r'ico.ico')
win.mainloop()

If you run the above program and then click on the ‘Plot APO Line’ button you will see the below outcome.

Like, share or follow me on Twitter.

March 18, 2019 02:10 PM UTC


Real Python

How to Build a Python GUI Application With wxPython

There are many graphical user interface (GUI) toolkits that you can use with the Python programming language. The big three are Tkinter, wxPython, and PyQt. Each of these toolkits will work with Windows, macOS, and Linux, with PyQt having the additional capability of working on mobile.

A graphical user interface is an application that has buttons, windows, and lots of other widgets that the user can use to interact with your application. A good example would be a web browser. It has buttons, tabs, and a main window where all the content loads.

In this article, you’ll learn how to build a graphical user interface with Python using the wxPython GUI toolkit.

Here are the topics covered:

Let’s start learning!

Free Bonus: Click here to get access to a chapter from Python Tricks: The Book that shows you Python's best practices with simple examples you can apply instantly to write more beautiful + Pythonic code.

Getting Started With wxPython

The wxPython GUI toolkit is a Python wrapper around a C++ library called wxWidgets. The initial release of wxPython was in 1998, so wxPython has been around quite a long time. wxPython’s primary difference from other toolkits, such as PyQt or Tkinter, is that wxPython uses the actual widgets on the native platform whenever possible. This makes wxPython applications look native to the operating system that it is running on.

PyQt and Tkinter both draw their widgets themselves, which is why they don’t always match the native widgets, although PyQt is very close.

This is not to say that wxPython does not support custom widgets. In fact, the wxPython toolkit has many custom widgets included with it, along with dozens upon dozens of core widgets. The wxPython downloads page has a section called Extra Files that is worth checking out.

Here, there is a download of the wxPython Demo package. This is a nice little application that demonstrates the vast majority of the widgets that are included with wxPython. The demo allows a developer to view the code in one tab and run it in a second tab. You can even edit and re-run the code in the demo to see how your changes affect the application.

Installing wxPython

You will be using the latest wxPython for this article, which is wxPython 4, also known as the Phoenix release. The wxPython 3 and wxPython 2 versions are built only for Python 2. When Robin Dunn, the primary maintainer of wxPython, created the wxPython 4 release, he deprecated a lot of aliases and cleaned up a lot of code to make wxPython more Pythonic and easier to maintain.

You will want to consult the following links if you are migrating from an older version of wxPython to wxPython 4 (Phoenix):

The wxPython 4 package is compatible with both Python 2.7 and Python 3.

You can now use pip to install wxPython 4, which was not possible in the legacy versions of wxPython. You can do the following to install it on your machine:

$ pip install wxpython

Note: On Mac OS X you will need a compiler installed such as XCode for the install to complete successfully. Linux may also require you to install some dependencies before the pip installer will work correctly.

For example, I needed to install freeglut3-dev, libgstreamer-plugins-base0.10-dev, and libwebkitgtk-3.0-dev on Xubuntu to get it to install.

Fortunately, the error messages that pip displays are helpful in figuring out what is missing, and you can use the prerequisites section on the wxPython Github page to help you find the information you need if you want to install wxPython on Linux.

There are some Python wheels available for the most popular Linux versions that you can find in the Extras Linux section with both GTK2 and GTK3 versions. To install one of these wheels, you would use the following command:

$ pip install -U -f https://extras.wxpython.org/wxPython4/extras/linux/gtk3/ubuntu-18.04/ wxPython

Be sure you have modified the command above to match your version of Linux.

Definition of a GUI

As was mentioned in the introduction, a graphical user interface (GUI) is an interface that is drawn on the screen for the user to interact with.

User interfaces have some common components:

All of these items are known generically as widgets. There are many other common widgets and many custom widgets that wxPython supports. A developer will take the widgets and arrange them logically on a window for the user to interact with.

Event Loops

A graphical user interface works by waiting for the user to do something. The something is called an event. Events happen when the user types something while your application is in focus or when the user uses their mouse to press a button or other widget.

Underneath the covers, the GUI toolkit is running an infinite loop that is called an event loop. The event loop just waits for events to occur and then acts on those events according to what the developer has coded the application to do. When the application doesn’t catch an event, it effectively ignores that it even happened.

When you are programming a graphical user interface, you will want to keep in mind that you will need to hook up each of the widgets to event handlers so that your application will do something.

There is a special consideration that you need to keep in mind when working with event loops: they can be blocked. When you block an event loop, the GUI will become unresponsive and appear to freeze to the user.

Any process that you launch in a GUI that will take longer than a quarter second should probably be launched as a separate thread or process. This will prevent your GUI from freezing and give the user a better user experience.

The wxPython framework has special thread-safe methods that you can use to communicate back to your application to let it know that the thread is finished or to give it an update.

Let’s create a skeleton application to demonstrate how events work.

Creating a Skeleton Application

An application skeleton in a GUI context is a user interface with widgets that don’t have any event handlers. These are useful for prototyping. You basically just create the GUI and present it to your stakeholders for sign-off before spending a lot of time on the backend logic.

Let’s start by creating a Hello World application with wxPython:

import wx

app = wx.App()
frame = wx.Frame(parent=None, title='Hello World')
frame.Show()
app.MainLoop()

Note: Mac users may get the following message: This program needs access to the screen. Please run with a Framework build of python, and only when you are logged in on the main display of your Mac. If you see this message and you are not running in a virtualenv, then you need to run your application with pythonw instead of python. If you are running wxPython from within a virtualenv, then see the wxPython wiki for the solution.

In this example, you have two parts: wx.App and the wx.Frame. The wx.App is wxPython’s application object and is required for running your GUI. The wx.App starts something called a .MainLoop(). This is the event loop that you learned about in the previous section.

The other piece of the puzzle is wx.Frame, which will create a window for the user to interact with. In this case, you told wxPython that the frame has no parent and that its title is Hello World. Here is what it looks like when you run the code:

Hello World in wxPython

Note: The application will look different when you run it on Mac or Windows.

By default, a wx.Frame will include minimize, maximize, and exit buttons along the top. You won’t normally create an application in this manner though. Most wxPython code will require you to subclass the wx.Frame and other widgets so that you can get the full power of the toolkit.

Let’s take a moment and rewrite your code as a class:

import wx

class MyFrame(wx.Frame):    
    def __init__(self):
        super().__init__(parent=None, title='Hello World')
        self.Show()

if __name__ == '__main__':
    app = wx.App()
    frame = MyFrame()
    app.MainLoop()

You can use this code as a template for your application. However, this application doesn’t do very much, so let’s take a moment to learn a little about some of the other widgets you could add.

Widgets

The wxPython toolkit has more than one hundred widgets to choose from. This allows you to create rich applications, but it can also be daunting trying to figure out which widget to use. This is why the wxPython Demo is helpful, as it has a search filter that you can use to help you find the widgets that might apply to your project.

Most GUI applications allow the user to enter some text and press a button. Let’s go ahead and add those widgets:

import wx

class MyFrame(wx.Frame):    
    def __init__(self):
        super().__init__(parent=None, title='Hello World')
        panel = wx.Panel(self)

        self.text_ctrl = wx.TextCtrl(panel, pos=(5, 5))
        my_btn = wx.Button(panel, label='Press Me', pos=(5, 55))

        self.Show()

if __name__ == '__main__':
    app = wx.App()
    frame = MyFrame()
    app.MainLoop()

When you run this code, your application should look like this:

Hello World in wxPython with widgets

The first widget you need to add is something called wx.Panel. This widget is not required, but recommended. On Windows, you are actually required to use a Panel so that the background color of the frame is the right shade of gray. Tab traversal is disabled without a Panel on Windows.

When you add the panel widget to a frame and the panel is the sole child of the frame, it will automatically expand to fill the frame with itself.

The next step is to add a wx.TextCtrl to the panel. The first argument for almost all widgets is which parent the widget should go onto. In this case, you want the text control and the button to be on top of the panel, so it is the parent you specify.

You also need to tell wxPython where to place the widget, which you can do by passing in a position via the pos parameter. In wxPython, the origin location is (0,0) which is the upper left corner of the parent. So for the text control, you tell wxPython that you want to position its top left corner 5 pixels from the left (x) and 5 pixels from the top (y).

Then you add your button to the panel and give it a label. To prevent the widgets from overlapping, you need to set the y-coordinate to 55 for the button’s position.

Absolute Positioning

When you provide exact coordinates for your widget’s position, the technique that you used is called absolute positioning. Most GUI toolkits provide this capability, but it’s not actually recommended.

As your application becomes more complex, it becomes difficult to keep track of all the widget locations and if you have to move the widgets around. Resetting all those positions becomes a nightmare.

Fortunately all modern GUI toolkits provide a solution for this, which is what you will learn about next.

Sizers (Dynamic Sizing)

The wxPython toolkit includes sizers, which are used for creating dynamic layouts. They manage the placement of your widgets for you and will adjust them when you resize the application window. Other GUI toolkits will refer to sizers as layouts, which is what PyQt does.

Here are the primary types of sizers that you will see used most often:

Let’s add a wx.BoxSizer to your example and see if we can make it work a bit more nicely:

import wx

class MyFrame(wx.Frame):    
    def __init__(self):
        super().__init__(parent=None, title='Hello World')
        panel = wx.Panel(self)        
        my_sizer = wx.BoxSizer(wx.VERTICAL)        
        self.text_ctrl = wx.TextCtrl(panel)
        my_sizer.Add(self.text_ctrl, 0, wx.ALL | wx.EXPAND, 5)        
        my_btn = wx.Button(panel, label='Press Me')
        my_sizer.Add(my_btn, 0, wx.ALL | wx.CENTER, 5)        
        panel.SetSizer(my_sizer)        
        self.Show()

if __name__ == '__main__':
    app = wx.App()
    frame = MyFrame()
    app.MainLoop()

Here you create an instance of a wx.BoxSizer and pass it wx.VERTICAL, which is the orientation that widgets are added to the sizer.

In this case, the widgets will be added vertically, which means they will be added one at a time from top to bottom. You may also set a BoxSizer’s orientation to wx.HORIZONTAL. When you do that, the widgets would be added from left to right.

To add a widget to a sizer, you will use .Add(). It accepts up to five arguments:

The window argument is the widget to be added while proportion sets how much space relative to other widgets in the sizer this particular widget should take. By default, it is zero, which tells wxPython to leave the widget at its default proportion.

The third argument is flag. You can actually pass in multiple flags if you wish as long as you separate them with a pipe character: |. The wxPython toolkit uses | to add flags using a series of bitwise ORs.

In this example, you add the text control with the wx.ALL and wx.EXPAND flags. The wx.ALL flag tells wxPython that you want to add a border on all sides of the widget while wx.EXPAND makes the widgets expand as much as they can within the sizer.

Finally, you have the border parameter, which tells wxPython how many pixels of border you want around the widget. The userData parameter is only used when you want to do something complex with your sizing of the widget and is actually quite rare to see in practice.

Adding the button to the sizer follows the exact same steps. However, to make things a bit more interesting, I went ahead and switched out the wx.EXPAND flag for wx.CENTER so that the button would be centered on-screen.

When you run this version of the code, your application should look like the following:

Hello World in wxPython with Sizers

If you’d like to learn more about sizers, the wxPython documentation has a nice page on the topic.

Adding an Event

While your application looks more interesting visually, it still doesn’t really do anything. For example, if you press the button, nothing really happens.

Let’s give the button a job:

import wx

class MyFrame(wx.Frame):    
    def __init__(self):
        super().__init__(parent=None, title='Hello World')
        panel = wx.Panel(self)        
        my_sizer = wx.BoxSizer(wx.VERTICAL)        
        self.text_ctrl = wx.TextCtrl(panel)
        my_sizer.Add(self.text_ctrl, 0, wx.ALL | wx.EXPAND, 5)        
        my_btn = wx.Button(panel, label='Press Me')
        my_btn.Bind(wx.EVT_BUTTON, self.on_press)
        my_sizer.Add(my_btn, 0, wx.ALL | wx.CENTER, 5)        
        panel.SetSizer(my_sizer)        
        self.Show()

    def on_press(self, event):
        value = self.text_ctrl.GetValue()
        if not value:
            print("You didn't enter anything!")
        else:
            print(f'You typed: "{value}"')

if __name__ == '__main__':
    app = wx.App()
    frame = MyFrame()
    app.MainLoop()

The widgets in wxPython allow you to attach event bindings to them so that they can respond to certain types of events.

Note: The code block above uses f-strings. You can read all about them in Python 3’s f-Strings: An Improved String Formatting Syntax (Guide).

You want the button to do something when the user presses it. You can accomplish this by calling the button’s .Bind() method. .Bind() takes the event you want to bind to, the handler to call when the event happens, an optional source, and a couple of optional ids.

In this example, you bind your button object to the wx.EVT_BUTTON event and tell it to call on_press() when that event gets fired.

An event gets “fired” when the user does the event you have bound to. In this case, the event that you set up is the button press event, wx.EVT_BUTTON.

.on_press() accepts a second argument that you can call event. This is by convention. You could call it something else if you wanted to. However, the event parameter here refers to the fact that when this method is called, its second argument should be an event object of some sort.

Within .on_press(), you can get the text control’s contents by calling its GetValue() method. You then print a string to stdout depending on what the contents of the text control is.

Now that you have the basics out of the way, let’s learn how to create an application that does something useful!

Creating a Working Application

The first step when creating something new is to figure out what you want to create. In this case, I have taken the liberty of making that decision for you. You will learn how to create a MP3 tag editor! The next step when creating something new is to find out what packages can help you accomplish your task.

If you do a Google search for Python mp3 tagging, you will find you have several options:

I tried out a couple of these and decided that eyeD3 had a nice API that you could use without getting bogged down with the MP3’s ID3 specification. You can install eyeD3 using pip, like this:

$ pip install eyed3

When installing this package on macOS, you may need to install libmagic using brew. Windows and Linux users shouldn’t have any issues installing eyeD3.

Designing the User Interface

When it comes to designing an interface, it’s always nice to just kind of sketch out how you think the user interface should look.

You will need to be able to do the following:

Most user interfaces use a menu or a button for opening files or folders. You can go with a File menu for this. Since you will probably want to see tags for multiple MP3 files, you will need to find a widget that can do this in a nice manner.

Something that is tabular with columns and rows would be ideal because then you can have labeled columns for the MP3 tags. The wxPython toolkit has a few widgets that would work for this, with the top two being the following:

You should use wx.ListCtrl in this case as the Grid widget is overkill, and frankly it is also quite a bit more complex. Finally, you need a button to use to edit a selected MP3’s tag.

Now that you know what you want, you can draw it up:

MP3 Editor in wxPython

The illustration above gives us an idea of how the application should look. Now that you know what you want to do, it’s time to code!

Creating the User Interface

There are many different approaches when it comes to writing a new application. For example, do you need to follow the Model-View-Controller design pattern? How do you split up the classes? One class per file? There are many such questions, and as you get more experienced with GUI design, you’ll know how you want to answer them.

In your case, you really only need two classes:

You could argue for creating a controller type module as well, but for something like this, you really do not need it. A case could also be made for putting each class into its own module, but to keep it compact, you will create a single Python file for all of your code.

Let’s start with imports and the panel class:

import eyed3
import glob
import wx

class Mp3Panel(wx.Panel):    
    def __init__(self, parent):
        super().__init__(parent)
        main_sizer = wx.BoxSizer(wx.VERTICAL)
        self.row_obj_dict = {}

        self.list_ctrl = wx.ListCtrl(
            self, size=(-1, 100), 
            style=wx.LC_REPORT | wx.BORDER_SUNKEN
        )
        self.list_ctrl.InsertColumn(0, 'Artist', width=140)
        self.list_ctrl.InsertColumn(1, 'Album', width=140)
        self.list_ctrl.InsertColumn(2, 'Title', width=200)
        main_sizer.Add(self.list_ctrl, 0, wx.ALL | wx.EXPAND, 5)        
        edit_button = wx.Button(self, label='Edit')
        edit_button.Bind(wx.EVT_BUTTON, self.on_edit)
        main_sizer.Add(edit_button, 0, wx.ALL | wx.CENTER, 5)        
        self.SetSizer(main_sizer)

    def on_edit(self, event):
        print('in on_edit')

    def update_mp3_listing(self, folder_path):
        print(folder_path)

Here, you import the eyed3 package, Python’s glob package, and the wx package for your user interface. Next, you subclass wx.Panel and create your user interface. You need a dictionary for storing data about your MP3s, which you can name row_obj_dict.

Then you create a wx.ListCtrl and set it to report mode (wx.LC_REPORT) with a sunken border (wx.BORDER_SUNKEN). The list control can take on a few other forms depending on the style flag that you pass in, but the report flag is the most popular.

To make the ListCtrl have the correct headers, you will need to call .InsertColumn() for each column header. You then supply the index of the column, its label, and how wide in pixels the column should be.

The last step is to add your Edit button, an event handler, and a method. You can create the binding to the event and leave the method that it calls empty for now.

Now you should write the code for the frame:

class Mp3Frame(wx.Frame):    
    def __init__(self):
        super().__init__(parent=None,
                         title='Mp3 Tag Editor')
        self.panel = Mp3Panel(self)
        self.Show()

if __name__ == '__main__':
    app = wx.App(False)
    frame = Mp3Frame()
    app.MainLoop()

This class is much simpler than the first one in that all you need to do is set the title of the frame and instantiate the panel class, Mp3Panel. When you are all done, your user interface should look like this:

wxPython MP3 Tag Editor

The user interface looks almost right, but you don’t have a File menu. This makes it impossible to add MP3s to the application and edit their tags!

Let’s fix that now.

Make a Functioning Application

The first step in making your application work is to update the application so that it has a File menu because then you can add MP3 files to your creation. Menus are almost always added to the wx.Frame class, so that is the class you need to modify.

Note: Some applications have moved away from having menus in their applications. One of the first to do so was Microsoft Office when they added the Ribbon Bar. The wxPython toolkit has a custom widget that you can use to create ribbons in wx.lib.agw.ribbon.

The other type of application that has dropped menus of late are web browsers, such as Google Chrome and Mozilla Firefox. They just use toolbars nowadays.

Let’s learn how to add a menu bar to our application:

class Mp3Frame(wx.Frame):

    def __init__(self):
        wx.Frame.__init__(self, parent=None, 
                          title='Mp3 Tag Editor')
        self.panel = Mp3Panel(self)
        self.create_menu()
        self.Show()

    def create_menu(self):
        menu_bar = wx.MenuBar()
        file_menu = wx.Menu()
        open_folder_menu_item = file_menu.Append(
            wx.ID_ANY, 'Open Folder', 
            'Open a folder with MP3s'
        )
        menu_bar.Append(file_menu, '&File')
        self.Bind(
            event=wx.EVT_MENU, 
            handler=self.on_open_folder,
            source=open_folder_menu_item,
        )
        self.SetMenuBar(menu_bar)

    def on_open_folder(self, event):
        title = "Choose a directory:"
        dlg = wx.DirDialog(self, title, 
                           style=wx.DD_DEFAULT_STYLE)
        if dlg.ShowModal() == wx.ID_OK:
            self.panel.update_mp3_listing(dlg.GetPath())
        dlg.Destroy()

Here, you add a call to .create_menu() within the class’s constructor. Then in .create_menu() itself, you will create a wx.MenuBar instance and a wx.Menu instance.

To add a menu item to a menu, you call the menu instance’s .Append() and pass it the following:

Next, you need to add the menu to the menubar, so you will need to call the menubar’s .Append(). It takes the menu instance and the label for menu. This label is a bit odd in that you called it &File instead of File. The ampersand tells wxPython to create a keyboard shortcut of Alt+F to open the File menu using just your keyboard.

Note: If you would like to add keyboard shortcuts to your application, then you will want to use an instance of wx.AcceleratorTable to create them. You can read more about Accerator Tables in the wxPython documentation.

To create an event binding, you will need to call self.Bind(), which binds the frame to wx.EVT_MENU. When you use self.Bind() for a menu event, you need to not only tell wxPython which handler to use, but also which source to bind the handler to.

Finally, you must call the frame’s .SetMenuBar() and pass it the menubar instance for it to be shown to the user.

Now that you have the menu added to your frame, let’s go over the menu item’s event handler, which is reproduced again below:

def on_open_folder(self, event):
    title = "Choose a directory:"
    dlg = wx.DirDialog(self, title, style=wx.DD_DEFAULT_STYLE)
    if dlg.ShowModal() == wx.ID_OK:
        self.panel.update_mp3_listing(dlg.GetPath())
    dlg.Destroy()

Since you want the user to choose a folder that contains MP3s, you will want to use wxPython’s wx.DirDialog. The wx.DirDialog allows the user to only open directories.

You can set the dialog’s title and various style flags. To show the dialog, you will need to call .ShowModal(). This will cause the dialog to show modally, which means that the user won’t be able to interact with your main application while the dialog is shown.

If the user presses the dialog’s OK button, you can get the user’s path choice via the dialog’s .GetPath(). You will want to pass that path to your panel class, which you can do here by calling the panel’s .update_mp3_listing().

Finally you need to close the dialog. To close a dialog, the recommended method is to call its .Destroy().

Dialogs do have a .Close() method, but that basically just hides the dialog, and it will not destroy itself when you close your application, which can lead to weird issues such as your application now shutting down properly. It’s simpler to call .Destroy() on the dialog to prevent this issue.

Now let’s update your Mp3Panel class. You can start by updating .update_mp3_listing():

def update_mp3_listing(self, folder_path):
    self.current_folder_path = folder_path
    self.list_ctrl.ClearAll()

    self.list_ctrl.InsertColumn(0, 'Artist', width=140)
    self.list_ctrl.InsertColumn(1, 'Album', width=140)
    self.list_ctrl.InsertColumn(2, 'Title', width=200)
    self.list_ctrl.InsertColumn(3, 'Year', width=200)

    mp3s = glob.glob(folder_path + '/*.mp3')
    mp3_objects = []
    index = 0
    for mp3 in mp3s:
        mp3_object = eyed3.load(mp3)
        self.list_ctrl.InsertItem(index, 
            mp3_object.tag.artist)
        self.list_ctrl.SetItem(index, 1, 
            mp3_object.tag.album)
        self.list_ctrl.SetItem(index, 2, 
            mp3_object.tag.title)
        mp3_objects.append(mp3_object)
        self.row_obj_dict[index] = mp3_object
        index += 1

Here you set the current directory to the specified folder and then you clear the list control. This keeps the list control fresh and only showing the MP3s that you are currently working on. That also means that you need to re-insert all the columns again.

Next, you’ll want to take the folder that was passed in and use Python’s glob module to search for MP3 files.

Then you can loop over the MP3s and turn them into eyed3 objects. You can do this by calling the .load() of eyed3. Assuming that the MP3s have the appropriate tags already, you can then add the artist, album, and title of the MP3 to the list control.

Interestingly, the method of adding a new row to a list control object is by calling .InsertItem() for the first column and SetItem() for all the subsequent columns.

The last step is to save off your MP3 object to your Python dictionary, row_obj_dict.

Now you need to update the .on_edit() event handler so that you can edit an MP3’s tags:

def on_edit(self, event):
    selection = self.list_ctrl.GetFocusedItem()
    if selection >= 0:
        mp3 = self.row_obj_dict[selection]
        dlg = EditDialog(mp3)
        dlg.ShowModal()
        self.update_mp3_listing(self.current_folder_path)
        dlg.Destroy()

The first thing you need to do is get the user’s selection by calling the list control’s .GetFocusedItem().

If the user has not selected anything in the list control, it will return -1. Assuming that the user did select something, you will want to extract the MP3 object from your dictionary and open a MP3 tag editor dialog. This will be a custom dialog that you will use to edit the artist, album, and title tags of the MP3 file.

As usual, show the dialog modally. When the dialog closes, the last two lines in .on_edit() will execute. These two lines will update the list control so it displays the current MP3 tag information that the user just edited and destroy the dialog.

Creating an Editing Dialog

The final piece of the puzzle is creating an MP3 tag editing dialog. For brevity, we will skip sketching out this interface as it is a series of rows that contains labels and text controls. The text controls should have the existing tag information pre-populated within them. You can create a label for the text controls by creating instances of wx.StaticText.

When you need to create a custom dialog, the wx.Dialog class is your friend. You can use that to design the editor:

class EditDialog(wx.Dialog):    
    def __init__(self, mp3):
        title = f'Editing "{mp3.tag.title}"'
        super().__init__(parent=None, title=title)        
        self.mp3 = mp3        
        self.main_sizer = wx.BoxSizer(wx.VERTICAL)        
        self.artist = wx.TextCtrl(
            self, value=self.mp3.tag.artist)
        self.add_widgets('Artist', self.artist)        
        self.album = wx.TextCtrl(
            self, value=self.mp3.tag.album)
        self.add_widgets('Album', self.album)        
        self.title = wx.TextCtrl(
            self, value=self.mp3.tag.title)
        self.add_widgets('Title', self.title)        
        btn_sizer = wx.BoxSizer()
        save_btn = wx.Button(self, label='Save')
        save_btn.Bind(wx.EVT_BUTTON, self.on_save)        
        btn_sizer.Add(save_btn, 0, wx.ALL, 5)
        btn_sizer.Add(wx.Button(
            self, id=wx.ID_CANCEL), 0, wx.ALL, 5)
        self.main_sizer.Add(btn_sizer, 0, wx.CENTER)        
        self.SetSizer(self.main_sizer)

Here you want to start off by sub-classing wx.Dialog and giving it a custom title based on the title of the MP3 that you are editing.

Next you can create the sizer you want to use and the widgets. To make things easier, you can create a helper method called .add_widgets() for adding the wx.StaticText widgets as rows with the text control instances. The only other widget here is the Save button.

Let’s write the add_widgets method next:

    def add_widgets(self, label_text, text_ctrl):
        row_sizer = wx.BoxSizer(wx.HORIZONTAL)
        label = wx.StaticText(self, label=label_text,
                              size=(50, -1))
        row_sizer.Add(label, 0, wx.ALL, 5)
        row_sizer.Add(text_ctrl, 1, wx.ALL | wx.EXPAND, 5)
        self.main_sizer.Add(row_sizer, 0, wx.EXPAND)

add_widgets() takes the label’s text and the text control instance. It then creates a horizontally oriented BoxSizer.

Next you will create an instance of wx.StaticText using the passed-in text for its label parameter. You will also set its size to be 50 pixels wide and the default height is set with a -1. Since you want the label before the text control, you will add the StaticText widget to your BoxSizer first and then add the text control .

Finally, you want to add the horizontal sizer to the top level vertical sizer. By nesting the sizers in each other, you can design complex applications.

Now you will need to create the on_save() event handler so that you can save your changes:

    def on_save(self, event):
        self.mp3.tag.artist = self.artist.GetValue()
        self.mp3.tag.album = self.album.GetValue()
        self.mp3.tag.title = self.title.GetValue()
        self.mp3.tag.save()
        self.Close()

Here you set the tags to the contents of the text controls and then call the eyed3 object’s .save(). Finally, you call the .Close() of the dialog. The reason you call .Close() here instead of .Destroy() is that you already call .Destroy() in the .on_edit() of your panel subclass.

Now your application is complete!

Conclusion

You learned a lot about wxPython in this article. You became familiar with the basics of creating GUI applications using wxPython.

You now know more about the following:

Finally you learned how to create a working application, an MP3 tag editor. You can use what you learned in this article to continue to enhance this application or perhaps create an amazing application on your own.

The wxPython GUI toolkit is robust and full of interesting widgets that you can use to build cross-platform applications. You are limited by only your imagination.

Further Reading

If you would like to learn more about wxPython, you can check out some of the following links:

For more information on what else you can do with Python, you might want to check out What Can I Do with Python? If you’d like to learn more about Python’s super(), then Supercharge Your Classes With Python super() may be just right for you.

You can also download the code for the MP3 tag editor application that you created in this article if you want to study it more in depth.


[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short & sweet Python Trick delivered to your inbox every couple of days. >> Click here to learn more and see examples ]

March 18, 2019 02:00 PM UTC


Podcast.__init__

Wes McKinney's Career In Python For Data Analysis

Python has become one of the dominant languages for data science and data analysis. Wes McKinney has been working for a decade to make tools that are easy and powerful, starting with the creation of Pandas, and eventually leading to his current work on Apache Arrow. In this episode he discusses his motivation for this work, what he sees as the current challenges to be overcome, and his hopes for the future of the industry.

Summary

Python has become one of the dominant languages for data science and data analysis. Wes McKinney has been working for a decade to make tools that are easy and powerful, starting with the creation of Pandas, and eventually leading to his current work on Apache Arrow. In this episode he discusses his motivation for this work, what he sees as the current challenges to be overcome, and his hopes for the future of the industry.

Announcements

  • Hello and welcome to Podcast.__init__, the podcast about Python and the people who make it great.
  • When you’re ready to launch your next app or want to try a project you hear about on the show, you’ll need somewhere to deploy it, so take a look at our friends over at Linode. With 200 Gbit/s private networking, scalable shared block storage, node balancers, and a 40 Gbit/s public network, all controlled by a brand new API you’ve got everything you need to scale up. And for your tasks that need fast computation, such as training machine learning models, they just launched dedicated CPU instances. Go to pythonpodcast.com/linode to get a $20 credit and launch a new server in under a minute. And don’t forget to thank them for their continued support of this show!
  • Visit the site to subscribe to the show, sign up for the newsletter, and read the show notes. And if you have any questions, comments, or suggestions I would love to hear them. You can reach me on Twitter at @Podcast__init__ or email hosts@podcastinit.com)
  • To help other people find the show please leave a review on iTunes and tell your friends and co-workers
  • Join the community in the new Zulip chat workspace at pythonpodcast.com/chat
  • Check out the Practical AI podcast from our friends at Changelog Media to learn and stay up to date with what’s happening in AI
  • You listen to this show to learn and stay up to date with the ways that Python is being used, including the latest in machine learning and data analysis. For even more opportunities to meet, listen, and learn from your peers you don’t want to miss out on this year’s conference season. We have partnered with O’Reilly Media for the Strata conference in San Francisco on March 25th and the Artificial Intelligence conference in NYC on April 15th. Here in Boston, starting on May 17th, you still have time to grab a ticket to the Enterprise Data World, and from April 30th to May 3rd is the Open Data Science Conference. Go to pythonpodcast.com/conferences to learn more and take advantage of our partner discounts when you register.
  • Your host as usual is Tobias Macey and today I’m interviewing Wes McKinney about his contributions to the Python community and his current projects to make data analytics easier for everyone

Interview

  • Introductions
  • How did you get introduced to Python?
  • You have spent a large portion of your career on building tools for data science and analytics in the Python ecosystem. What is your motivation for focusing on this problem domain?
  • Having been an open source author and contributor for many years now, what are your current thoughts on paths to sustainability?
  • What are some of the common challenges pertaining to data analysis that you have experienced in the various work environments and software projects that you have been involved in?
    • What area(s) of data science and analytics do you find are not receiving the attention that they deserve?
  • Recently there has been a lot of focus and excitement around the capabilities of neural networks and deep learning. In your experience, what are some of the shortcomings or blind spots to that class of approach that would be better served by other classes of solution?
  • Your most recent work is focused on the Arrow project for improving interoperability across languages. What are some of the cases where a Python developer would want to incorporate capabilities from other runtimes?
    • Do you think that we should be working to replicate some of those capabilities into the Python language and ecosystem, or is that wasted effort that would be better spent elsewhere?
  • Now that Pandas has been in active use for over a decade and you have had the opportunity to get some space from it, what are your thoughts on its success?
    • With the perspective that you have gained in that time, what would you do differently if you were starting over today?
  • You are best known for being the creator of Pandas, but can you list some of the other achievements that you are most proud of?
  • What projects are you most excited to be working on in the near to medium future?
  • What are your grand ambitions for the future of the data science community, both in and outside of the Python ecosystem?
  • Do you have any parting advice for active or aspiring data scientists, or resources that you would like to recommend?

Keep In Touch

Picks

Links

The intro and outro music is from Requiem for a Fish The Freak Fandango Orchestra / CC BY-SA

March 18, 2019 10:32 AM UTC


Zato Blog

HTTP Method and Accept headers

Zato 3.1 includes new means to manage access to REST services based on input Method and Accept headers in HTTP requests - here is how they can be employed in practice.

A bit of background

Prior to Zato 3.1, one could always build a REST API reacting to individual HTTP verbs by implementing handle_VERB methods in services, such as:

class MyService(Service):

    def handle_GET(self):
        # Reacts to GET requests
        pass

    def handle_POST(self):
        # Reacts to POST requests
        pass

    # Any other handle_VERB method will be used accordingly

This works and will continue to work as expected in all future Zato versions.

However, one aspect of it is that, if one uses SimpleIO, keeping all handler methods in the same service means that all of them share the same SIO definition which is not always desirable - for instance, input to POST may be unrelated to input that DELETE receives.

REST channel URL paths

In Zato 3.1 and newer, it is possible to create REST channels that have the same URL path but different services mounted on each channel, separately for each HTTP verb requires.

That is, whereas previously it was a single service with multiple handle_VERB methods, now it can be a set of services, each reacting to a different HTTP verb and all of them mounted on the same URL path.

In a way, this was supported previously but, if handle_VERB methods were not used, URL paths had to be distinct, e.g.

GET /api/user
DELETE /api/user/delete
POST /api/user/create

In 3.1+, this can be simplified to:

GET /api/user
DELETE /api/user
POST /api/user

Now, each of the combination of verb + path may be unique for a REST channel while previously each channel needed to have its own URL path.

Moreover, because each channel may have its own separate service, it also means that each service may have its own SimpleIO definition and that the service becomes less tied to REST.

HTTP Accept headers

This is a completely new feature in 3.1 which lets one have distinct REST channels depending on the requests's Accept headers.

For instance, let's say that we would like to process incoming invoices under POST /api/invoice but we would like to have two services reacting to the same endpoint, one for JSON and now for PDF invoices.

This can be achieved by configuring HTTP Accept headers in their channels, as below - note that the method and URL path are the same in both cases yet HTTP Accept and services are different because each service reacts to a different value of HTTP Accept:

HTTP Accept header patterns

We can go one better and take advantage of Accept header patterns - with an asterisk meaning any character - this will configure the channel to process requests matching any value that fits in with the pattern, e.g. text/* will mean text/csv, text/xml or anything that starts with text/.

However, seeing as it can be a number of input MIME types, at this point we may need to know what the actual value was - this can be extracted from the WSGI environment via self.wsgi_environ.

Summary

Zato 3.1 saw improvements and backward-compatible changes to how REST channels can be built.

It will now support more use-cases, such as single URL path channels with different HTTP verbs and independent SimpleIO definitions or HTTP Accept headers different for each channel.

In turn, this lets one build REST APIs that are more flexible and elastic in their design to react to different input criteria.

March 18, 2019 09:38 AM UTC


Django Weblog

Django 2.2 release candidate 1 released

Django 2.2 release candidate 1 is the final opportunity for you to try out the salmagundi of new features before Django 2.2 is released.

The release candidate stage marks the string freeze and the call for translators to submit translations. Provided no major bugs are discovered that can't be solved in the next two weeks, Django 2.2 will be released on or around April 1. Any delays will be communicated on the django-developers mailing list thread.

Please use this opportunity to help find and fix bugs (which should be reported to the issue tracker). You can grab a copy of the package from our downloads page or on PyPI.

The PGP key ID used for this release is Carlton Gibson: E17DF5C82B4F9D00.

March 18, 2019 08:40 AM UTC


codingdirectional

Create a sports score application with python

Hello and welcome back. In this chapter, we will create a small sports score application with the help of the sports.py module. We will create a simple application to retrieve the score of the NBA result for any two particular teams and prints it on the tkinter’s text widget. Before we start, you will need to download the sports.py module to your own computer. Since the module is on pypi.org all you need is to open up your windows command prompt and type in below line to download that module! As I have mentioned earlier, I am now using visual studio 2019 to develop this new python project.

pip install sports.py

Now just start the visual studio 2019 then type the below code into the code editor.

import sports
import json
from tkinter import *
import tkinter.ttk as tk

win = Tk() # Create tk instance
win.title("NBA") # Add a title 
win.resizable(0, 0) # Disable resizing the GUI
win.configure(background='white') # change window background color

selectorFrame = Frame(win, background="white") # create top frame to hold team 1 vs team 2 combobox
selectorFrame.pack(anchor = "nw", pady = 2, padx=10)
match_label = Label(selectorFrame, text = "Select Team 1 vs Team 2 :", background="white")
match_label.pack(anchor="w") # the team label

# Create a combo box for team 1
team1 = tk.Combobox(selectorFrame)
team1.pack(side = LEFT, padx=3)

# Create a combo box for team 2
team2 = tk.Combobox(selectorFrame)
team2.pack(side = LEFT, padx=3)

s = StringVar() # create string variable
# create match frame and text widget to display the incoming match data
matchFrame = Frame(win)
matchFrame.pack(side=TOP)
match = Label(matchFrame)
match.pack()
text_widget = Text(match, fg='white', background='black')
text_widget.pack()
s.set("Click the find button to find out the match result")
text_widget.insert(END, s.get())

buttonFrame = Frame(win) # create a bottom frame to hold the find button
buttonFrame.pack(side = BOTTOM, fill=X, pady = 6)

# fill up the combo boxes with the team name data from the text file
team_tuple = tuple()
f = open("TextFile1.txt", "r")
for line in f.readlines():
    line = line.replace('\n', '')
    team_tuple += (line, )
f.close()

team1["values"] = team_tuple
team1.current(1)
team2["values"] = team_tuple
team2.current(0)

def get_match(): # return the recent match of team 1 vs team 2
   
    try:
        match = sports.get_match(sports.BASKETBALL, team1.get(), team2.get())
        text_widget.delete('1.0', END) # clear all those previous text first
        s.set(match)
        text_widget.insert(INSERT, s.get()) # display team match data in text widget
    except:
        print("An exception occurred")

action_vid = tk.Button(buttonFrame, text="Find", command=get_match) # button used to find out the team match data
action_vid.pack()

win.mainloop()

Select the debug tab then start debugging the program.

In the next chapter, we will further modify this sports score application, maybe with other module and API because there are a few shortages in this current module.

March 18, 2019 07:02 AM UTC


Mike Driscoll

PyDev of the Week: Bruno Rocha

This week we welcome Bruno Rocha (@rochacbruno) as our PyDev of the Week! Bruno works for Red Hat and participates in the Python, Flask and Rust communities. You can see some of his projects over on Github or check out some of his writings on Medium. Let’s take a few moments to get to know Bruno better!

Can you tell us a little about yourself (hobbies, education, etc):

I’m Bruno Rocha, Software Engineer from São Paulo, Brazil.

I started playing with computers at a very young age when I was 12 when my mother gave me an old IBM XT 5160. After a few days playing DOOM and studying LOTUS 123 worksheets, I naturally became the computer boy in the family. I did a course of MS.DOS 6.22 (the novelty of that time) and learned to program some things with BASIC and dBase, a few years later the web appeared in Brazil and I started to make HTML sites with CGI in Perl and also to create programs with macros in MS Access 95.

I worked for some years as an instructor in basic computer courses, some jobs as a web designer, I also worked with network installation, PC building, and in 1998 I met Linux through Conectiva (A Brazilian Red Hat based distro). I got involved with Open Source and Linux and then I became sysadmin in hybrid networks with Linux and Windows NT.

Years later I joined the University of Information Systems and I graduated, during graduation I fell in love with programming and since then I have been working with software development, started some small business (in the days when we did not call it “startup”), I worked for Palm Inc. developed drivers and sales force systems for Palm OS with C, developed portals and CMS for several large companies in Brazil, taught online Python courses, worked in the Data Science team of the largest Job board in Brazil and since 2016 I have been dedicated to Quality Engineering and Test Automation at Red Hat.

Besides software and computers, I am vegetarian since I was born, and vegan for more than 15 years. I have been very active in animal rights activism movements and also in the rescue of abandoned animals (currently taking care of 32 rescued animals).

In my free time I love cooking vegan food but my favorite hobby is road cycling, I have participated in some vintage bike races with my Bianchi 1973 and my Caloi-10 1980, recently I became father of a boy, Erik is 3 months old and life has changed a little and since then my favorite hobby has been to sleep when I can.

Why did you start using Python?

In the early 2000s I was focused on bringing Linux to the desktops of the companies for which I provided SysAdmin services, Knoppix (Linux from Live CD) came out, and in Brazil I got involved with the community around the Linux distribution called Kurumin Linux. The innovation in this Linux was the so-called “Magic Icons” many written in Python and one of these icons led to an interactive tutorial on Python, that’s when I had my first contact and then I started contributing to this community.

The idea of bringing Linux to Desktops failed, but in compensation I learned Python that very soon became useful in other areas with the emergence of web frameworks like Pylons, Turbogears and Django.

Despite working with different technologies like .NET, PHP to pay the bills every day I got more involved with Python and adopted it as my preferred language for projects, around 2008 I became a core committer and one of Web2py’s most active contributors. I started organizing meetups, talking at many community events and large conferences, in 2012 I co-authored a book on web development with Python and in same year I was nominated a Fellow member of the Python Software Foundation where I still work in 2 workgroups.

Since 2008 I have worked exclusively with Python in different areas, teaching, maintaining some open-source libraries, more heavily involved in web with Django and Flask and more recently focused on automation of tests and Quality Engineering.

What other programming languages do you know and which is your favorite?

I am fluent in C, C#, Javascript, Bash, PHP, Perl, Lua, Python and currently learning Rust.

In addition to Python (of course) because it is the technology and community that has supported me for almost 15 years, if I had to choose just one language I would choose Rust because it is an innovative language, it gives me the feeling that I am doing things in the right way, it’s very challenging and everything indicates that it will have a bright future! (or rather, rusty future)

What projects are you working on now?

I created some open-source projects mostly around Flask, one of them is Flasgger (horrible name) which is an extension to create Swagger APIs. I have also created a CMS with Flask and NoSQL called Quokka CMS, and some other extensions for Flask that are currently being maintained by the community since I am not having much time available to devote myself to these projects.

The only project I actively maintain is a library called Dynaconf, it is a Python configuration manager, with extensions for Django and Flask, which aims to facilitate the management of settings dynamically with support for various file formats, environments and databases.

Professionally I work on Pulp Project, which is part of Red Hat Satellite and Ansible Galaxy. Pulp is a Django application that controls the distribution of software packages. My role is on development of Pulp-Smash a functional testing framework for exercising Pulp.

In addition I have been teaching Python and Quality Engineering, I share some stuff on CursoDePython YouTube channel (in Portuguese) and co-host the Castálio podcast.

Which Python libraries are your favorite (core or 3rd party)?

Inside the standard library I greatly admire Functools and Contextlib, I really like meta programming and I have used these 2 libraries in almost all of my projects.

3rd party I would like to mention Poetry, I believe that Poetry is the “package manager” that every Pythonist has always dreamed of, and this tool needs more attention because currently it is the one that best solve the problems of dependencies and distribution.

Is there anything else you’d like to say?

I want to use this space to thank immensely all the “social developers,” people who devote their time and wisdom to creating social impact projects that are already changing the world, technology is a good source of income but the most important thing is “transformation of the world” and what still gives me energy for open-source is knowing that the little I do with open-source can somehow help social impact projects.

And last but not the least; Go Vegan!.

Thanks for doing the interview, Bruno!

March 18, 2019 05:05 AM UTC


leftmouseclickin

Plotting the Chaikin AD line graph

Our Own Score

In this chapter, we will create a method to plot the Chaikin AD line graph with the help from the alpha vantage module. The Accumulation Distribution Line (ADL) is used by Chaikin Oscillator to measure the movements of a stock.

We will include a button to call the plot ad method to plot the AD line graph.

import json
from tkinter import *
import tkinter.ttk as tk
from alpha_vantage.foreignexchange import ForeignExchange
from alpha_vantage.techindicators import TechIndicators
from alpha_vantage.timeseries import TimeSeries
import matplotlib.pyplot as plt
from alpha_vantage.sectorperformance import SectorPerformances

win = Tk() # Create tk instance
win.title("Real Forex n Stock") # Add a title
win.resizable(0, 0) # Disable resizing the GUI
win.configure(background='white') # change window background color

selectorFrame = Frame(win, background="white") # create the top frame to hold base and quote currency combobox
selectorFrame.pack(anchor = "nw", pady = 2, padx=10)
currency_label = Label(selectorFrame, text = "Select base currency / quote currency :", background="white")
currency_label.pack(anchor="w") # the currency pair label

selector1Frame = Frame(win, background="white") # create the middle frame to hold base and quote currency combobox
selector1Frame.pack(anchor = "nw", pady = 2, padx=10)
stock_label = Label(selector1Frame, text = "Select Stock :", background="white")
stock_label.pack(anchor="w") # the stock label

curr1 = tuple() # the tuple which will be populated by base and quote currency
currency_list = ['AUD', 'BCH', 'BNB', 'BND', 'BTC', 'CAD', 'CHF', 'CNY', 'EOS', 'EUR', 'ETH', 'GBP', 'HKD', 'JPY', 'LTC', 'NZD', 'MYR', 'TRX', 'USD', 'USDT', 'XLM', 'XRP'] # major world currency pairs

# populate the combo box for both the base and quote currency
for key in currency_list:
    curr1 += (key, )

# populate the stock symbol tuple
f = open("stock.txt", "r")
curr2 = tuple()
for line in f.readlines():
    curr2 += (line.replace('\n', ''),)
f.close()

# Create a combo box for base currency
base_currency = StringVar() # create a string variable
based = tk.Combobox(selectorFrame, textvariable=base_currency)
based['values'] = curr1
based.pack(side = LEFT, padx=3)

# Create a combo box for quote currency
quote_currency = StringVar() # create a string variable
quote = tk.Combobox(selectorFrame, textvariable=quote_currency)
quote['values'] = curr1
quote.pack(side = LEFT, padx=3)

# Create a combo box for stock items
stock_symbol = StringVar() # create a string variable
stock = tk.Combobox(selector1Frame, textvariable=stock_symbol)
stock['values'] = curr2
stock.current(0)
stock.pack(side = LEFT, padx=3)

interval = tk.Combobox(selector1Frame)
interval['values'] = ('1min', '5min', '15min', '30min', '60min', 'daily', 'weekly', 'monthly')
interval.current(0)
interval.pack(side = LEFT, padx=3)

price_type = tk.Combobox(selector1Frame)
price_type['values'] = ('close', 'open', 'high', 'low')
price_type.current(0)
price_type.pack(side =LEFT, padx=3)

matype_type = tk.Combobox(selector1Frame, width=37)
matype_type['values'] = ('Simple Moving Average (SMA)', 'Exponential Moving Average (EMA)', 'Weighted Moving Average (WMA)', 'Double Exponential Moving Average (DEMA', 'Triple Exponential Moving Average (TEMA)', 'Triangular Moving Average (TRIMA', 'T3 Moving Average', 'Kaufman Adaptive Moving Average (KAMA)', ' MESA Adaptive Moving Average (MAMA)')
matype_type.current(0)
matype_type.pack(side =LEFT, padx=3)
mattype_list = ['Simple Moving Average (SMA)', 'Exponential Moving Average (EMA)', 'Weighted Moving Average (WMA)', 'Double Exponential Moving Average (DEMA', 'Triple Exponential Moving Average (TEMA)', 'Triangular Moving Average (TRIMA', 'T3 Moving Average', 'Kaufman Adaptive Moving Average (KAMA)', ' MESA Adaptive Moving Average (MAMA)']

s = StringVar() # create string variable which will be used to fill up the Forex data
# create currency frame and text widget to display the incoming forex data
currencyFrame = Frame(win)
currencyFrame.pack(side=TOP)
currency = Label(currencyFrame)
currency.pack(fill=X)
text_widget = Text(currency, fg='white', background='black')
text_widget.pack(fill=X)
s.set("Click the find button to find out the currency exchange rate")
text_widget.insert(END, s.get())

buttonFrame = Frame(win) # create a bottom frame to hold the find button
buttonFrame.pack(side = BOTTOM, fill=X, pady = 6, padx=10)

# first get the api key and secret from the file
f = open("alpha.txt", "r")
api_key = f.readline()
f.close()
api_key = api_key.replace('\n', '')

def get_exchange_rate(): # this method will display the incoming forex data after the api called

    try:
        cc = ForeignExchange(key= api_key)
        from_ = based.get()
        to_ = quote.get()

        countVar = StringVar()  # use to hold the character count
        text_widget.tag_remove("search", "1.0", "end")  # cleared the hightlighted currency pair

        if(from_ != '' and to_ != '' and from_ != to_):
            data, _ = cc.get_currency_exchange_rate(from_currency=from_, to_currency=to_)
            exchange_rate = dict(json.loads(json.dumps(data)))
            count = 1
            sell_buy = str(count) + ".) Pair : " + exchange_rate['1. From_Currency Code'] + "(" + exchange_rate['2. From_Currency Name'] + ")" + " / " + exchange_rate['3. To_Currency Code']+"(" + exchange_rate['4. To_Currency Name'] + ") : "  + str(exchange_rate['5. Exchange Rate']) + '\n'
            text_widget.delete('1.0', END)  # clear all those previous text first
            s.set(sell_buy)
            text_widget.insert(INSERT, s.get())  # display forex rate in text widget
            pos = text_widget.search(from_, "1.0", stopindex="end", count=countVar)
            text_widget.tag_configure("search", background="green")
            end_pos = float(pos) + float(0.7)
            text_widget.tag_add("search", pos, str(end_pos))  # highlight the background of the searched currency pair
            pos = float(pos) + 2.0
            text_widget.see(str(pos))

    except:
        print("An exception occurred")

def plot_stock_echange():

    try:
        stock_symbol_text = stock.get() # get the selected symbol
        if(stock_symbol_text!= ''):
            ts = TimeSeries(key=api_key, output_format='pandas')
            data, meta_data = ts.get_intraday(symbol=stock_symbol_text, interval='1min', outputsize='full')
            data['4. close'].plot()
            stock_title = 'Intraday Times Series for the ' + stock_symbol_text + ' stock (1 min)'
            plt.title(stock_title)
            plt.show()
    except:
        print("An exception occurred")

def plot_stock_technical():

    try:
        stock_symbol_text = stock.get() # get the selected stock symbol
        if(stock_symbol_text!= ''):

            ti = TechIndicators(key=api_key, output_format='pandas')
            data, meta_data = ti.get_bbands(symbol=stock_symbol_text, interval=interval.get(), series_type=price_type.get(), matype=mattype_list.index(matype_type.get()), time_period=int(interval.get().replace('min', '')))
            data.plot()
            stock_title = 'BBbands indicator for ' + stock_symbol_text + ' ' + interval.get()
            plt.title(stock_title)
            plt.show()
    except:
        print("An exception occurred")

def plot_sector_performance():

    sp = SectorPerformances(key=api_key, output_format='pandas')
    data, meta_data = sp.get_sector()
    data['Rank A: Real-Time Performance'].plot(kind='bar')
    plt.title('Real Time Performance (%) per Sector')
    plt.tight_layout()
    plt.grid()
    plt.show()

def plot_ad(): # plot the AD line

    try:
        stock_symbol_text = stock.get()  # get the selected stock symbol
        if (stock_symbol_text != ''):
            ti = TechIndicators(key=api_key, output_format='pandas')
            data, meta_data = ti.get_ad(symbol=stock_symbol_text, interval=interval.get())
            data.plot()
            stock_title = 'Chaikin A/D line values for ' + stock_symbol_text + ' ' + interval.get()
            plt.title(stock_title)
            plt.show()
    except:
        print("An exception occurred")

action_vid = tk.Button(buttonFrame, text="Calculate Exchange Rate", command=get_exchange_rate) # button used to find out the exchange rate of currency pair
action_vid.pack(side=LEFT, padx=2)
action_stock_plot = tk.Button(buttonFrame, text="Plot Stock", command=plot_stock_echange) # button used to plot the intra-minute stock value
action_stock_plot.pack(side=LEFT, padx=2)
action_technical_plot = tk.Button(buttonFrame, text="Plot Technical", command=plot_stock_technical) # button used to plot the 60 minutes stock technical value
action_technical_plot.pack(side=LEFT, padx=2)
action_sector_plot = tk.Button(buttonFrame, text="Plot Sector Performance", command=plot_sector_performance) # button used to plot the sector performance graph
action_sector_plot.pack(side=LEFT, padx=2)
action_ad_plot = tk.Button(buttonFrame, text="Plot AD Line", command=plot_ad) # button used to plot the A/D line graph
action_ad_plot.pack(side=LEFT, padx=2)

win.iconbitmap(r'ico.ico')
win.mainloop()

Anticipating trend changes in the Accumulation Distribution Line can help chartists anticipate trend changes in the underlying security.

Let us take a look at the Chaikin AD line of one the stocks below within the time interval of 60 minutes.

I am thinking of putting this project online soon and this project will get updated weekly with the latest feature, so stay tune. Like, share or follow me on Twitter if you want more Forex and Stock programming tips.

March 18, 2019 04:02 AM UTC


Montreal Python User Group

Montréal-Python 74: Call for speakers - Virtual Echo

Spring is upon us and it's time for Pythonistas to gather and discuss the latest news and their latest projects.

For this occasion we are looking for speakers who would like to share their latest discoveries. This is the best opportunity to reach out to the Montreal python community.

To submit your talk, write us at the following address: mtlpyteam@googlegroups.com or join us on Slack at https://mtlpy.org/slackin.

When

Monday April 1st 2019 at 6pm

Where

Shopify, 490 rue de la Gauchetière Montréal, Québec (map) https://goo.gl/maps/FccEH2n7EPm

Schedule

6:00PM - Doors open 6:30PM - Presentations 8:00PM - End of the event 8:15PM - Benelux

March 18, 2019 04:00 AM UTC


Techiediaries - Django

Django Authentication — Login, Logout and Password Change/Reset

In this tutorial, you'll learn how to easily add a complete authentication system to your Django application with login, logout and password change and reset functionalities.

We'll be using Django with a MySQL database.

We'll also be using django-crispy-forms and Bootstrap 4 for styling the application UI.

Prerequisites

Let's start with the prerequisites for this tutorial. In order to follow the tutorial step by step, you'll need a few requirements, such as:

We will be using pip and venv which are bundled as modules in recent versions of Python so you don't actually need to install them unless you are working with old versions.

If you are ready, lets go started!

Creating a Virtual Environment

A virtual environment allows you to isolate your current project dependencies from the rest of packages installed globally on your system or in the other virtual environments. You can either use virtualenv which needs to be installed on your system or the venv module available as a module in recent versions of Python 3.

Go to your command terminal and run:

$ python -m venv env

Next, activate the virtual environment using:

$ source env/bin/activate

Note: please note that on Windows, you need to use source env/Scripts/activate in order to activate your virtual environment.

After activating the environment, you need to proceed by installing Django using pip:

$ pip install django

If the framework is successfully installed, you can now use the Django management commands to create and work with your project.

We'll also need to install mysql-client using:

$ pip install mysqlclient

Creating a MySQL Database

We'll be using a MySQL database. In your terminal invoke the mysql client using the following command:

$ mysql -u root -p

Enter your MySQL password and hit Enter.

Next, run the following SQL statement to create a database:

mysql> create database mydb;

Creating a Django Project

Let's now create the project using django-admin.py. In your terminal, run the following command:

$ django-admin.py startproject demoproject

Django has an ORM that abstracts dircet database operations and supports SQLite which is configured by default in the project so we'll be using a SQLite database for this tutorial.

If you need to use PostgreSQL, MySQL or any other database management system, you'll have to install it first then open the settings.py of your project and add the database address and credentials inside the DATABASES object.

Here is the configuration for mysql:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql', 
        'NAME': 'mydb',
        'USER': 'root',
        'PASSWORD': 'YOUR_DB_PASSWORD',
        'HOST': 'localhost',   
        'PORT': '3306',
    }    
}

Make sure to replace YOUR_DB_PASSWORD with your own MySQL password.

Adding django-crispy-forms

We'll be using Bootstrap 4 for styling the authentication forms, so you need to install it using pip:

$ pip install django-crispy-forms

Next, open the settings.py file and add the application to the installed apps:

INSTALLED_APPS = [
    # [...]
    'crispy_forms'
]

Next, add the following setting which sets Bootstrap 4 as the default styling framework for django-crispy-forms:

CRISPY_TEMPLATE_PACK =  'bootstrap4'

Creating the accounts Application

Apps are the Django way of organizing a project. Think of them as modules.

Let's encapsulate the authentication logic needed in our project into an accounts application. You obviously use any valid name you see fit.

Go to your terminal and navigate inside your project's folder if you have not done so:

$ cd demoproject

Next, create the application using manage.py:

$ python manage.py startapp accounts

manage.py is another management script for Django that exists in your root project's folder. It provides a nice wrapper for the most used Django management commands.

The previous command will create a Django application with a default file structure. To make this app part of your project, you need to open the settings.py file and add it to the INSTALLED_APPS array:

INSTALLED_APPS = [
# [...]
'accounts'
]

That's it, you can now create your database and run your Django development server using the following commands:

$ python manage.py migrate
$ python manage.py runserver

You can use your browser to navigate to the localhost:8000 address in order to see you web application up and running.

The auth Built-In Application

The auth application is a built-in authentication system in Django that allows developers to add authentication to their apps without re-inventing the wheel trying to implement the base functionality from scratch.

The Django authentication app provides the following functionalities out of the box:

You only need to provide templates to implement these functions in your application.

For registering users, you need to create your view and template.

You need to have the django.contrib.auth app in the INSTALLED_APPS of the settings.py file which is the case by default.

Next create the urls.py file in your accounts app and add the following code:

from django.contrib.auth import views
from django.urls import path

urlpatterns = [
]

Login Users Using LoginView

You can login users in your Django application using the LoginView class-based view. In your accounts/urls.py file add the following path:

 urlpatterns = [
    path('login/', views.LoginView.as_view(), name='login'),

You simply use the as_view() method of LoginView to return a callback object that can be assigned as a view function to the path() function.

Next, you need to provide a template for your login view. Create a templates folder in the root of your accounts application and add a base.html file with the following code:

<!doctype  html>
<html  lang="en">
<head>
<link  rel="stylesheet"  href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"  integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"  crossorigin="anonymous">
<title>Django Authentication Example</title>
</head>
<body>
  <div  class="container">
    <div  class="row justify-content-center">
      <div  class="col-4">
      <h1  class="text-center">Django Authentication Example</h1>
      {% block main %}
      {% endblock %}
      </div>
    </div>
  </div>
</body>
</html>

We first import Bootstrap 4 in our base HTML template. We then create a container <div> a title and a main block where Django render the other parts of our templates.

Next, create a templates/registration folder and the the login.html template with the following code:

{% extends  'base.html' %}
{% load crispy_forms_tags %}

{% block main %}
<div class="card">
<div class="card-body">
<h4 class="card-title">Log in to your account</h4>

<form method="post">
{% csrf_token %}
<input type="hidden" name="next" value="{{ next }}">

{{ form|crispy }}

<button type="submit" class="btn btn-primary btn-block">Log in</button>
</form>
</div>
</div>
{% endblock %}

We extend the previous base template, we load crispy_forms_tags and then we override the main block to add our login form.

Next, we create an HTML form with a POST method and render the form fields using `. Thecrispy` filter applies Bootstrap styles to the individual fields.

csrf_token adds the field for CSRF protection to out login form.

We Also add a hidden form field that holds the next URL that will be used by Django to redirect the user to a next page when he's successfully logged in. By default it redirects the accounts/profile URL.

Setting the Login Redirect URL

You can set the next URL or the login redirect URL via the LOGIN_REDIRECT_URL setting. Open the settings.py file and add:

LOGIN_REDIRECT_URL =  '/'

For testing the login view, you can create a user using the manage.py createsuperuser command from your terminal.

Note: Once you are logged in, you will be redirected to the /accounts/profile URL.

This is a screenshot of the login form styled with Bootstrap 4:

Django login form

Logout Users Using LogoutView

You can logout users in your application using the LogoutView class-based view. In your accounts.py file, add the /logout path and link it with a callable view of LogoutView:

   path('logout/', views.LogoutView.as_view(), name='logout'),

Again we use the as_view() method to return a callable object from the LogoutView class.

Next, you need to create a registration/logged_out.html with the following code:

{% extends 'base.html' %}
{% block main %}

<p>You are logged out!</p>
<a  href="{% url 'login' %}">Log in again</a>

{% endblock %}

This is a screenshot of the logged-out done view:

Django logout done

Reset Passwords Using PasswordResetView, PasswordResetDoneView, PasswordResetConfirmView and PasswordResetCompleteView

You can enable your users to reset their passwords using many views:

In your accounts/urls.py file, add the following paths:

path('password-reset/', views.PasswordResetView.as_view(), name='password_reset'),
path('password-reset/done/', views.PasswordResetDoneView.as_view(), name='password_reset_done'),
path('reset/<uidb64>/<token>/', views.PasswordResetConfirmView.as_view(), name='password_reset_confirm'),
path('reset/done/', views.PasswordResetCompleteView.as_view(), name='password_reset_complete'),

Next, you need to add a registration/password_reset_form.html template with the following code:

{% extends 'base.html' %}
{% load crispy_forms_tags %}

{% block main %}
<div  class="card">
<div  class="card-body">
<h4  class="card-title">Reset your password</h4>
<form  method="post">
{% csrf_token %}
<input  type="hidden"  name="next"  value="{{ next }}">
{{ form|crispy }}

<button  type="submit"  class="btn btn-primary btn-block">Reset</button>
</form>
</div>
</div>
</div>
{% endblock %}

In the same way, you need to add the password_reset_confirm.html, password_reset_done.html, password_reset_email.html and password_reset_complete.html templates.

This is a screenshot of the password reset form styled with Bootstrap 4:

Django password reset form

Changing Passwords Using PasswordChangeView and PasswordChangeDoneView

You can enable your users to change their passwords via the PasswordChangeView and PasswordChangeDoneView class-based views.

In your accounts/views.py file, add the following paths:

path('password-change/', views.PasswordChangeView.as_view(), name='password_change'),
path('password-change/done/', views.PasswordChangeDoneView.as_view(), name='password_change_done'),

Next create a registration/password_change_form.html template and add the following code:

{% extends 'base.html' %}
{% load crispy_forms_tags %}

{% block main %}
<div  class="card">
<div  class="card-body">
<h4  class="card-title"> Change your password</h4>

<form  method="post">
{% csrf_token %}
{{ form|crispy }}

<button  type="submit"  class="btn btn-success">Change password </button>
</form>
</div>
</div>
{% endblock %}

You also need to add password_change_done.html template.

This is a screenshot of the password change form:

Django password change form

Registering Users

For registering users, the Django built-in auth application doesn't provide a ready view function or class-based view so you need to provide your own your own custom implementation.

Importing the URLs in your Projects' urls.py

You have added the various urls for implementing authentication in your web application in the accounts application but they can not be used until you add them to the project's level urls.py file .

First, this is the complete source of the accounts/urls.py file:

from django.contrib.auth import views
from django.urls import path

urlpatterns = [
    path('login/', views.LoginView.as_view(), name='login'),
    path('logout/', views.LogoutView.as_view(), name='logout'),
    path('password-change/', views.PasswordChangeView.as_view(), name='password_change'),
    path('password-change/done/', views.PasswordChangeDoneView.as_view(), name='password_change_done'),
    path('password-reset/', views.PasswordResetView.as_view(), name='password_reset'),
    path('password-reset/done/', views.PasswordResetDoneView.as_view(), name='password_reset_done'),
    path('reset/<uidb64>/<token>/', views.PasswordResetConfirmView.as_view(), name='password_reset_confirm'),
    path('reset/done/', views.PasswordResetCompleteView.as_view(), name='password_reset_complete'),
]

Next, open the urls.py that exists in the root of your project and use the include() function to import the accounts urls:

from django.urls import path, include

urlpatterns = [
    path('accounts/', include('accounts.urls'))
]

Now, go ahead and start your development server. You can use your authentication URLs under the /accounts path:

Conclusion

Throughout this tutorial we've seen how we can easily add the login, logout and password reset and change features in our Django apps using the auth application without re-inventing the wheel.

We've also used Bootstrap 4 and django-crispy-forms to style the various forms for login, password change and reset.

March 18, 2019 12:00 AM UTC

March 17, 2019


gamingdirectional

Put the power bar on the game scene

Finally we have came to the last chapter of this pygame project, in this chapter we will put three things on the game scene, a text which indicates what is the power level of the player, a game level indicator as well as a power bar which shows the power level of that player in the graphic form. We will need to edit three files in order to create such a mechanism. The first file we need to edit is...

Source

March 17, 2019 05:33 AM UTC


leftmouseclickin

Further modifying the Bollinger Bands features

Our Own Score

In this chapter, we will further modify the previous plot_stock_technical method which uses to plot the Bollinger Bands graph. We will create a few combo boxes that offer various extra parameters that will be used to plot the Bollinger Band for any selected stock. The result is amazing after this edit.

Below are some facts about the Bollinger Bands.


Developed by John Bollinger, Bollinger Bands® are volatility bands placed above and below a moving average. Volatility is based on the standard deviation, which changes as volatility increases and decreases. The bands automatically widen when volatility increases and contract when volatility decreases. Their dynamic nature allows them to be used on different securities with the standard settings. For signals, Bollinger Bands can be used to identify M-Tops and W-Bottoms or to determine the strength of the trend. Signals derived from narrowing BandWidth are discussed in the ChartSchool article on BandWidth.

Here is the modify version of the current ongoing Stock and Forex project.

import json
from tkinter import *
import tkinter.ttk as tk
from alpha_vantage.foreignexchange import ForeignExchange
from alpha_vantage.techindicators import TechIndicators
from alpha_vantage.timeseries import TimeSeries
import matplotlib.pyplot as plt
from alpha_vantage.sectorperformance import SectorPerformances

win = Tk() # Create tk instance
win.title("Real Forex n Stock") # Add a title
win.resizable(0, 0) # Disable resizing the GUI
win.configure(background='white') # change window background color

selectorFrame = Frame(win, background="white") # create the top frame to hold base and quote currency combobox
selectorFrame.pack(anchor = "nw", pady = 2, padx=10)
currency_label = Label(selectorFrame, text = "Select base currency / quote currency :", background="white")
currency_label.pack(anchor="w") # the currency pair label

selector1Frame = Frame(win, background="white") # create the middle frame to hold base and quote currency combobox
selector1Frame.pack(anchor = "nw", pady = 2, padx=10)
stock_label = Label(selector1Frame, text = "Select Stock :", background="white")
stock_label.pack(anchor="w") # the stock label

curr1 = tuple() # the tuple which will be populated by base and quote currency
currency_list = ['AUD', 'BCH', 'BNB', 'BND', 'BTC', 'CAD', 'CHF', 'CNY', 'EOS', 'EUR', 'ETH', 'GBP', 'HKD', 'JPY', 'LTC', 'NZD', 'MYR', 'TRX', 'USD', 'USDT', 'XLM', 'XRP'] # major world currency pairs

# populate the combo box for both the base and quote currency
for key in currency_list:
    curr1 += (key, )

# populate the stock symbol tuple
f = open("stock.txt", "r")
curr2 = tuple()
for line in f.readlines():
    curr2 += (line.replace('\n', ''),)
f.close()

# Create a combo box for base currency
base_currency = StringVar() # create a string variable
based = tk.Combobox(selectorFrame, textvariable=base_currency)
based['values'] = curr1
based.pack(side = LEFT, padx=3)

# Create a combo box for quote currency
quote_currency = StringVar() # create a string variable
quote = tk.Combobox(selectorFrame, textvariable=quote_currency)
quote['values'] = curr1
quote.pack(side = LEFT, padx=3)

# Create a combo box for stock items
stock_symbol = StringVar() # create a string variable
stock = tk.Combobox(selector1Frame, textvariable=stock_symbol)
stock['values'] = curr2
stock.current(0)
stock.pack(side = LEFT, padx=3)

interval = tk.Combobox(selector1Frame)
interval['values'] = ('1min', '5min', '15min', '30min', '60min', 'daily', 'weekly', 'monthly')
interval.current(0)
interval.pack(side = LEFT, padx=3)

price_type = tk.Combobox(selector1Frame)
price_type['values'] = ('close', 'open', 'high', 'low')
price_type.current(0)
price_type.pack(side =LEFT, padx=3)

matype_type = tk.Combobox(selector1Frame, width=37)
matype_type['values'] = ('Simple Moving Average (SMA)', 'Exponential Moving Average (EMA)', 'Weighted Moving Average (WMA)', 'Double Exponential Moving Average (DEMA', 'Triple Exponential Moving Average (TEMA)', 'Triangular Moving Average (TRIMA', 'T3 Moving Average', 'Kaufman Adaptive Moving Average (KAMA)', ' MESA Adaptive Moving Average (MAMA)')
matype_type.current(0)
matype_type.pack(side =LEFT, padx=3)
mattype_list = ['Simple Moving Average (SMA)', 'Exponential Moving Average (EMA)', 'Weighted Moving Average (WMA)', 'Double Exponential Moving Average (DEMA', 'Triple Exponential Moving Average (TEMA)', 'Triangular Moving Average (TRIMA', 'T3 Moving Average', 'Kaufman Adaptive Moving Average (KAMA)', ' MESA Adaptive Moving Average (MAMA)']

s = StringVar() # create string variable which will be used to fill up the Forex data
# create currency frame and text widget to display the incoming forex data
currencyFrame = Frame(win)
currencyFrame.pack(side=TOP)
currency = Label(currencyFrame)
currency.pack(fill=X)
text_widget = Text(currency, fg='white', background='black')
text_widget.pack(fill=X)
s.set("Click the find button to find out the currency exchange rate")
text_widget.insert(END, s.get())

buttonFrame = Frame(win) # create a bottom frame to hold the find button
buttonFrame.pack(side = BOTTOM, fill=X, pady = 6, padx=10)

# first get the api key and secret from the file
f = open("alpha.txt", "r")
api_key = f.readline()
f.close()
api_key = api_key.replace('\n', '')

def get_exchange_rate(): # this method will display the incoming forex data after the api called

    try:
        cc = ForeignExchange(key= api_key)
        from_ = based.get()
        to_ = quote.get()

        countVar = StringVar()  # use to hold the character count
        text_widget.tag_remove("search", "1.0", "end")  # cleared the hightlighted currency pair

        if(from_ != '' and to_ != '' and from_ != to_):
            data, _ = cc.get_currency_exchange_rate(from_currency=from_, to_currency=to_)
            exchange_rate = dict(json.loads(json.dumps(data)))
            count = 1
            sell_buy = str(count) + ".) Pair : " + exchange_rate['1. From_Currency Code'] + "(" + exchange_rate['2. From_Currency Name'] + ")" + " / " + exchange_rate['3. To_Currency Code']+"(" + exchange_rate['4. To_Currency Name'] + ") : "  + str(exchange_rate['5. Exchange Rate']) + '\n'
            text_widget.delete('1.0', END)  # clear all those previous text first
            s.set(sell_buy)
            text_widget.insert(INSERT, s.get())  # display forex rate in text widget
            pos = text_widget.search(from_, "1.0", stopindex="end", count=countVar)
            text_widget.tag_configure("search", background="green")
            end_pos = float(pos) + float(0.7)
            text_widget.tag_add("search", pos, str(end_pos))  # highlight the background of the searched currency pair
            pos = float(pos) + 2.0
            text_widget.see(str(pos))

    except:
        print("An exception occurred")

def plot_stock_echange():

    try:
        stock_symbol_text = stock.get() # get the selected symbol
        if(stock_symbol_text!= ''):
            ts = TimeSeries(key=api_key, output_format='pandas')
            data, meta_data = ts.get_intraday(symbol=stock_symbol_text, interval='1min', outputsize='full')
            data['4. close'].plot()
            stock_title = 'Intraday Times Series for the ' + stock_symbol_text + ' stock (1 min)'
            plt.title(stock_title)
            plt.show()
    except:
        print("An exception occurred")

def plot_stock_technical():

    try:
        stock_symbol_text = stock.get() # get the selected stock symbol
        if(stock_symbol_text!= ''):

            ti = TechIndicators(key=api_key, output_format='pandas')
            data, meta_data = ti.get_bbands(symbol=stock_symbol_text, interval=interval.get(), series_type=price_type.get(), matype=mattype_list.index(matype_type.get()), time_period=int(interval.get().replace('min', '')))
            data.plot()
            stock_title = 'BBbands indicator for ' + stock_symbol_text + ' ' + interval.get()
            plt.title(stock_title)
            plt.show()
    except:
        print("An exception occurred")

def plot_sector_performance():

    sp = SectorPerformances(key=api_key, output_format='pandas')
    data, meta_data = sp.get_sector()
    data['Rank A: Real-Time Performance'].plot(kind='bar')
    plt.title('Real Time Performance (%) per Sector')
    plt.tight_layout()
    plt.grid()
    plt.show()

action_vid = tk.Button(buttonFrame, text="Calculate Exchange Rate", command=get_exchange_rate) # button used to find out the exchange rate of currency pair
action_vid.pack(side=LEFT, padx=2)
action_stock_plot = tk.Button(buttonFrame, text="Plot Stock", command=plot_stock_echange) # button used to plot the intra-minute stock value
action_stock_plot.pack(side=LEFT, padx=2)
action_technical_plot = tk.Button(buttonFrame, text="Plot Technical", command=plot_stock_technical) # button used to plot the 60 minutes stock technical value
action_technical_plot.pack(side=LEFT, padx=2)
action_sector_plot = tk.Button(buttonFrame, text="Plot Sector Performance", command=plot_sector_performance) # button used to plot the sector performance graph
action_sector_plot.pack(side=LEFT, padx=2)

win.iconbitmap(r'ico.ico')
win.mainloop()

We will continue develop this python application in the next chapter.

March 17, 2019 03:42 AM UTC

March 16, 2019


Weekly Python StackOverflow Report

(clxix) stackoverflow python report

These are the ten most rated questions at Stack Overflow last week.
Between brackets: [question score / answers count]
Build date: 2019-03-16 20:11:00 GMT


  1. Python if-else code style for reduced code for rounding floats - [17/11]
  2. Why is (2^31) >> 32 not 0? - [12/1]
  3. Python: Check if string and its substring are existing in the same list - [11/5]
  4. Convert dataframe into dictionary - [10/2]
  5. How do I slice a string by characters in Python? - [8/5]
  6. Fastest way to pop N items from a large dict - [8/2]
  7. Why is AdamOptimizer duplicated in my graph? - [8/0]
  8. How the dtype of numpy array is calculated internally? - [7/2]
  9. Why is `arr.take(idx)` faster than `arr[idx]` - [7/0]
  10. Python type hint for classes that support __getitem__ - [6/3]

March 16, 2019 08:11 PM UTC


Python Bytes

#121 python2 becomes self-aware, enters fifth stage of grief

March 16, 2019 08:00 AM UTC


codingdirectional

Create a new Python Project with Visual Studio 2019 RC IDE

Hello people, after a while of rest I have started a new python project today which I believe will take almost a month to complete. I will update the progress of this project at least a few times per week on this website so make sure you visit this website constantly to receive the latest project update.

In this chapter, we will just create the new project and then writing a few lines of python code that will create a tkinter pop up windows. As you might have guessed from the above title, yes we are going to use the Visual Studio 2019 RC IDE to create this latest python project. I have downloaded the IDE and most of the components yesterday, and today I am ready to get to work, not only for this python project but also for two other projects that will create the application for windows 10 with c sharp and javascript.

If you have not yet downloaded the visual studio 2019 then you can head over to the official website of visual studio to download the installer which will then help you to install visual studio as well as all the python components that are needed in our project. The download size of the python components are not that huge so you should have no problem to download all the python components that you need for this project.

The download size for the python components is around 1.84 GB

After you have downloaded the visual studio IDE plus the python components we can then start a brand new python project.

Select Python Application when create a new project in visual studio

The next step you need to do is to fill up all the project details and press the next button then the create button to create a brand new python project.

Fill up the project details

You can clearly see your project files from the solution explorer.

The file name is YouData.py

Now you can start to type in the below code to the code editing panel. After that select Debug->Start Debugging.

from tkinter import *
import tkinter.ttk as tk

win = Tk() # Create tk instance
win.title("Collect Youtube Keyword Ranking") # Add a title
win.resizable(0, 0) # Disable resizing the GUI
win.configure(background='black') # change window background color

win.mainloop()

You will see the tkinter window plus the default command prompt pop up on the screen.

This means the debugging process has completed and there is no error in that python code

We will talk about the python project details in the next chapter.

March 16, 2019 06:59 AM UTC

Return a reverse order list for a number with python

Hello people, this will be the last article which we will solve a simple question in CodeWars, in the next chapter we will start our next python project. In this chapter, we will solve one of the questions in CodeWars and the question goes like this.

Given a number, find the reverse order’s numbers of that number until one and put them in a list. For example, number 6 will make the method to return a list of reverse numbers up until 1, [6,5,4,3,2,1]. Below is the solution.

def reverse_seq(n):

    list_ = []
    while(n > 0):
        list_.append(n)
        n -= 1
    return list_

So we have solved that simple question on CodeWars and we have received 2 kyu from our hard work. With that, we have temporary concluded the question solving chapter and will start our next python project in the next chapter.

March 16, 2019 06:12 AM UTC