Planet Python

Subscribe to Planet Python feed
Planet Python - http://planetpython.org/
Updated: 2 hours 7 min ago

Python for Beginners: Postorder Tree Traversal Algorithm in Python

Thu, 2021-12-02 11:26

Binary trees are very useful in representing hierarchical data. In this article, we will discuss how to print all the elements in a binary tree using postorder tree traversal. We will also implement the postorder tree traversal algorithm in python.

What is the postorder tree traversal algorithm?

Postorder traversal algorithm is a depth first traversal algorithm. Here, we start from a root node and traverse a branch of the tree until we reach the end of the branch. After that, we move to the next branch. This process continues until all the nodes in the tree are printed. 

The postorder tree traversal algorithm gets its name from the order in which the nodes of a tree are printed. In this algorithm, we first print the left sub-tree of the node, then we print the right sub-tree of the current node. At last, we print the current node. This process is recursive in nature. Here, the node is only printed when all the nodes in the left sub-tree and the right sub-tree of the current node have already been printed.  

Let us understand the process using the binary tree given in the following image.

Binary Tree

Let us print all of the nodes in the above binary tree using the postorder traversal algorithm.

  • We will start from the node 50. Before printing 50, we have to print its left sub-tree and right sub-tree. So, we will move to 20.
  • Before printing 20, we have to print its left sub-tree and right sub-tree. So, we will move to 11.
  • As 11 has no children, we will print 11. After that we will move to the previous node i.e. 20.
  • As the left child of 20 has already been printed, we will move to the right sub-tree of 20 i.e. 22.
  • As 22 has no children, we will print 22. After that we will move to the previous node i.e. 20.
  • As both the left sub-tree and the right sub-tree of 20 have already been printed. We will print 20 and will move to its parent node i.e. 50.
  • At this point, Left sub-tree of 50 has already been printed.So, will print its right sub-tree. We will move to 53.
  • Before printing 53, we have to print its left sub-tree and right sub-tree. So, we will move to 52.
  • As 52 has no children, we will print 52. After that we will move to the previous node i.e. 53.
  • As the left child of 53 has already been printed, we will move to the right sub-tree of 53 i.e. 78.
  • As 78 has no children, we will print 78. After that we will move to the previous node i.e. 53.
  • As both the left sub-tree and the right sub-tree of 53 have already been printed, We will print 53 and will move to its parent node i.e. 50.
  • At this point,  both the left sub-tree and the right sub-tree of 50 have already been printed, So, we will print 50.
  • As all the nodes in the tree have already been printed, we will terminate this algorithm.

You can observe that we have printed the values in the order 11, 22, 20,52, 78, 53, 50. Let us now formulate an algorithm for the postorder tree traversal algorithm.

Algorithm for postorder tree traversal

As you have an overview of the entire process, we can formulate the algorithm for postorder tree traversal as follows.

  1. Start from the root node.
  2. If the root is empty, return.
  3. Traverse the left sub-tree recursively.
  4. Traverse the right sub-tree recursively.
  5. Print the root node.
  6. Stop.
Implementation of postorder tree traversal in Python

 As we have understood the algorithm for postorder tree traversal and its working, Let us implement the algorithm and execute it for the binary tree given in the above image.

class BinaryTreeNode: def __init__(self, data): self.data = data self.leftChild = None self.rightChild = None def postorder(root): # if root is None,return if root is None: return # traverse left subtree postorder(root.leftChild) # traverse right subtree postorder(root.rightChild) # print the current node print(root.data, end=" ,") def insert(root, newValue): # if binary search tree is empty, create a new node and declare it as root if root is None: root = BinaryTreeNode(newValue) return root # if newValue is less than value of data in root, add it to left subtree and proceed recursively if newValue < root.data: root.leftChild = insert(root.leftChild, newValue) else: # if newValue is greater than value of data in root, add it to right subtree and proceed recursively root.rightChild = insert(root.rightChild, newValue) return root root = insert(None, 50) insert(root, 20) insert(root, 53) insert(root, 11) insert(root, 22) insert(root, 52) insert(root, 78) print("Postorder traversal of the binary tree is:") postorder(root)

Output:

Postorder traversal of the binary tree is: 11 ,22 ,20 ,52 ,78 ,53 ,50 , Conclusion

In this article, we have discussed and implemented the postorder tree traversal algorithm. To learn more about other tree traversal algorithms, you can read this article on Inorder tree traversal algorithm or level order tree traversal algorithm in python.

The post Postorder Tree Traversal Algorithm in Python appeared first on PythonForBeginners.com.

Categories: FLOSS Project Planets

Inspired Python: Testing your Python Code with Hypothesis

Thu, 2021-12-02 10:31
Testing your Python Code with Hypothesis

I can think of a several Python packages that greatly improved the quality of the software I write. Two of them are pytest and hypothesis. The former adds an ergonomic framework for writing tests and fixtures and a feature-rich test runner. The latter adds property-based testing that can ferret out all but the most stubborn bugs using clever algorithms, and that’s the package we’ll explore in this course.

In an ordinary test you interface with the code you want to test by generating one or more inputs to test against, and then you validate that it returns the right answer. But that, then, raises a tantalizing question: what about all the inputs you didn’t test? Your code coverage tool may well report 100% test coverage, but that does not, ipso facto, mean the code is bug-free.

One of the defining features of Hypothesis is its ability to generate test cases automatically in a manner that is:

So let’s look at how Hypothesis can help you discover errors in your code.



Read More ->
Categories: FLOSS Project Planets

John Ludhi/nbshare.io: Amazon Review Summarization Using GPT-2 And PyTorch

Thu, 2021-12-02 05:38
Amazon Review Summarization Using GPT-2 And PyTorch

Since its reveal in 2017 in the popular paper Attention Is All You Need (https://arxiv.org/abs/1706.03762), the Transformer quickly became the most popular model in NLP. The ability to process text in a non-sequential way (as opposed to RNNs) allowed for training of big models. The attention mechanism it introduced proved extremely useful in generalizing text.

Following the paper, several popular transformers surfaced, the most popular of which is GPT. GPT models are developed and trained by OpenAI, one of the leaders in AI research. The latest release of GPT is GPT-3, which has 175 billion parameters. The model was very advanced to the point where OpenAI chose not to open-source it. People can access it through an API after a signup process and a long queue.

However, GPT-2, their previous release is open-source and available on many deep learning frameworks.

In this excercise, we use Huggingface and PyTorch to fine-tune a GPT-2 model for review summarization.

Overview:

  • Imports and Data Loading
  • Data Preprocessing
  • Setup and Training
  • Summary Writing
Imports and Data Loading In [ ]: !pip install transformers In [2]: import re import random import pandas as pd import numpy as np import torch from torch.utils.data import Dataset, DataLoader from transformers import AutoTokenizer, AutoModelWithLMHead import torch.optim as optim

We set the device to enable GPU processing.

In [3]: device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu') device Out[3]: device(type='cuda', index=0) In [4]: from google.colab import drive drive.mount("/content/drive") Mounted at /content/drive

The data we will use for training summarization is the Amazon review dataset, which can be found at https://www.kaggle.com/currie32/summarizing-text-with-amazon-reviews.

When writing a review on Amazon, customers write a review and a title for the review. The dataset treats the title as the summary of the review.

In [5]: reviews_path = "/content/drive/My Drive/Colab Notebooks/reviews.txt"

We use the standard python method of opening txt files:

In [6]: with open(reviews_path, "r") as reviews_raw: reviews = reviews_raw.readlines()

Showing 5 instances:

In [7]: reviews[:5] Out[7]: ['I have bought several of the Vitality canned dog food products and have found them all to be of good quality. The product looks more like a stew than a processed meat and it smells better. My Labrador is finicky and she appreciates this product better than most. = Good Quality Dog Food\n', 'Product arrived labeled as Jumbo Salted Peanuts...the peanuts were actually small sized unsalted. Not sure if this was an error or if the vendor intended to represent the product as "Jumbo". = Not as Advertised\n', 'This is a confection that has been around a few centuries. It is a light, pillowy citrus gelatin with nuts - in this case Filberts. And it is cut into tiny squares and then liberally coated with powdered sugar. And it is a tiny mouthful of heaven. Not too chewy, and very flavorful. I highly recommend this yummy treat. If you are familiar with the story of C.S. Lewis\' "The Lion, The Witch, and The Wardrobe" - this is the treat that seduces Edmund into selling out his Brother and Sisters to the Witch. = "Delight" says it all\n', 'If you are looking for the secret ingredient in Robitussin I believe I have found it. I got this in addition to the Root Beer Extract I ordered (which was good) and made some cherry soda. The flavor is very medicinal. = Cough Medicine\n', 'Great taffy at a great price. There was a wide assortment of yummy taffy. Delivery was very quick. If your a taffy lover, this is a deal. = Great taffy\n']

As shown, each sample consists of the review followed by its summary, separated by the equals (=) sign.

In [8]: len(reviews) Out[8]: 70993

There are ~71K instances in the dataset, which is sufficient to train a GPT-2 model.

Data Preprocessing

The beauty of GPT-2 is its ability to multi-task. The same model can be trained on more than 1 task at a time. However, we should adhere to the correct task designators, as specified by the oriningal paper.

For summarization, the appropriate task designator is the TL;DR symbol, which stands for "too long; didn't read".

The "TL;DR" token should be between the input text and the summary.

Thus, we will replace the equals symbol in the data with the correct task designator:

In [9]: reviews = [review.replace(" = ", " TL;DR ") for review in reviews] In [10]: reviews[10] Out[10]: 'One of my boys needed to lose some weight and the other didn\'t. I put this food on the floor for the chubby guy, and the protein-rich, no by-product food up higher where only my skinny boy can jump. The higher food sits going stale. They both really go for this food. And my chubby boy has been losing about an ounce a week. TL;DR My cats LOVE this "diet" food better than their regular food\n'

So far, so good.

Finally for preprocessing, we should acquire a fixed length input. We use the average review length (in words) as an estimator:

In [11]: avg_length = sum([len(review.split()) for review in reviews])/len(reviews) avg_length Out[11]: 53.41132224303804

Since the average instance length in words is 53.3, we can assume that a max length of 100 will cover most of the instances.

In [12]: max_length = 100 Setup and Training

Before creating the Dataset object, we download the model and the tokenizer. We need the tokenizer in order to tokenize the data.

In [ ]: tokenizer = AutoTokenizer.from_pretrained("gpt2") model = AutoModelWithLMHead.from_pretrained("gpt2") In [ ]: model_pth = "/content/drive/My Drive/Colab Notebooks/gpt2_weights_reviews" model.load_state_dict(torch.load(model_pth))

We send the model to the device and initialize the optimizer

In [14]: model = model.to(device) In [15]: optimizer = optim.AdamW(model.parameters(), lr=3e-4)

To correctly pad and truncate the instances, we find the number of tokens used by the designator " TL;DR ":

In [16]: tokenizer.encode(" TL;DR ") Out[16]: [24811, 26, 7707, 220] In [17]: extra_length = len(tokenizer.encode(" TL;DR "))

We create a simple dataset that extends the PyTorch Dataset class:

In [18]: class ReviewDataset(Dataset): def __init__(self, tokenizer, reviews, max_len): self.max_len = max_len self.tokenizer = tokenizer self.eos = self.tokenizer.eos_token self.eos_id = self.tokenizer.eos_token_id self.reviews = reviews self.result = [] for review in self.reviews: # Encode the text using tokenizer.encode(). We add EOS at the end tokenized = self.tokenizer.encode(review + self.eos) # Padding/truncating the encoded sequence to max_len padded = self.pad_truncate(tokenized) # Creating a tensor and adding to the result self.result.append(torch.tensor(padded)) def __len__(self): return len(self.result) def __getitem__(self, item): return self.result[item] def pad_truncate(self, name): name_length = len(name) - extra_length if name_length < self.max_len: difference = self.max_len - name_length result = name + [self.eos_id] * difference elif name_length > self.max_len: result = name[:self.max_len + 3]+[self.eos_id] else: result = name return result

Then, we create the dataset:

In [19]: dataset = ReviewDataset(tokenizer, reviews, max_length)

Using a batch_size of 32, we create the dataloader (Since the reviews are long, increasing the batch size can result in out of memory errors):

In [20]: dataloader = DataLoader(dataset, batch_size=32, shuffle=True, drop_last=True)

GPT-2 is capable of several tasks, including summarization, generation, and translation. To train for summarization, use the same as input as labels:

In [21]: def train(model, optimizer, dl, epochs): for epoch in range(epochs): for idx, batch in enumerate(dl): with torch.set_grad_enabled(True): optimizer.zero_grad() batch = batch.to(device) output = model(batch, labels=batch) loss = output[0] loss.backward() optimizer.step() if idx % 50 == 0: print("loss: %f, %d"%(loss, idx)) In [22]: train(model=model, optimizer=optimizer, dl=dataloader, epochs=1) loss: 6.946306, 0 loss: 2.313275, 50 loss: 2.081371, 100 loss: 2.080384, 150 loss: 2.071196, 200 loss: 2.179309, 250 loss: 1.935419, 300 loss: 2.011451, 350 loss: 1.980574, 400 loss: 1.855210, 450 loss: 1.986903, 500 loss: 2.003548, 550 loss: 2.083431, 600 loss: 1.981340, 650 loss: 1.922457, 700 loss: 2.141630, 750 loss: 2.239510, 800 loss: 2.168324, 850 loss: 2.148268, 900 loss: 1.916848, 950 loss: 1.999705, 1000 loss: 2.087286, 1050 loss: 1.794339, 1100 loss: 2.022352, 1150 loss: 1.772905, 1200 loss: 2.076683, 1250 loss: 1.713505, 1300 loss: 1.870195, 1350 loss: 1.819874, 1400 loss: 2.044860, 1450 loss: 1.827045, 1500 loss: 2.027030, 1550 loss: 1.979240, 1600 loss: 1.786424, 1650 loss: 2.288711, 1700 loss: 1.786224, 1750 loss: 2.204020, 1800 loss: 1.959004, 1850 loss: 1.924462, 1900 loss: 1.971964, 1950 loss: 1.797068, 2000 loss: 1.862133, 2050 loss: 1.898281, 2100 loss: 2.193818, 2150 loss: 2.005977, 2200

The online server I used was going to go offline, therefore I had to stop training a few batches early. The KeyboardInterrupt error should not be an issue, since the model's weights are saved.

The loss decreased consistently, which means that the model was learning.

Review Summarization

The summarization methodology is as follows:

  1. A review is initially fed to the model.
  2. A choice from the top-k choices is selected.
  3. The choice is added to the summary and the current sequence is fed to the model.
  4. Repeat steps 2 and 3 until either max_len is achieved or the EOS token is generated.
In [23]: def topk(probs, n=9): # The scores are initially softmaxed to convert to probabilities probs = torch.softmax(probs, dim= -1) # PyTorch has its own topk method, which we use here tokensProb, topIx = torch.topk(probs, k=n) # The new selection pool (9 choices) is normalized tokensProb = tokensProb / torch.sum(tokensProb) # Send to CPU for numpy handling tokensProb = tokensProb.cpu().detach().numpy() # Make a random choice from the pool based on the new prob distribution choice = np.random.choice(n, 1, p = tokensProb) tokenId = topIx[choice][0] return int(tokenId) In [24]: def model_infer(model, tokenizer, review, max_length=15): # Preprocess the init token (task designator) review_encoded = tokenizer.encode(review) result = review_encoded initial_input = torch.tensor(review_encoded).unsqueeze(0).to(device) with torch.set_grad_enabled(False): # Feed the init token to the model output = model(initial_input) # Flatten the logits at the final time step logits = output.logits[0,-1] # Make a top-k choice and append to the result result.append(topk(logits)) # For max_length times: for _ in range(max_length): # Feed the current sequence to the model and make a choice input = torch.tensor(result).unsqueeze(0).to(device) output = model(input) logits = output.logits[0,-1] res_id = topk(logits) # If the chosen token is EOS, return the result if res_id == tokenizer.eos_token_id: return tokenizer.decode(result) else: # Append to the sequence result.append(res_id) # IF no EOS is generated, return after the max_len return tokenizer.decode(result)

Generating unique summaries for a 5 sample reviews:

In [30]: sample_reviews = [review.split(" TL;DR ")[0] for review in random.sample(reviews, 5)] sample_reviews Out[30]: ["My local coffee shop has me addicted to their 20 oz vanilla chai lattes. At $3.90 a pop I was spending a lot of money. I asked what brand they used, need nutritional information, of course! They told me it was Big Train Chai Vanilla.<br />It's important to follow the directions on the can. I made mine with just milk with a yucky result. Use the water with a little milk as there is milk powder in the mix.<br /><br />WARNING:It's addicting!!!", 'popcorn is very good. but only makes about half of it.tast so good like moive theater popcorn.so so so goooooooooooooooooood', "Love these chips. Good taste,very crispy and very easy to clean up the entire 3 oz. bag in one sitting. NO greasy after-taste. Original and barbecue flavors are my favorites but I haven't tried all flavors. Great product.", 'We have not had saltines for many years because of unwanted ingredients. This brand is yummy and contains no unwanted ingredients. It was also a lot cheaper by the case than at the local supermarket.', "Best English Breakfast tea for a lover of this variety and I've tried so many including importing it from England. After s 20 year search I've found a very reasonable price for a most falvorful tea."] In [31]: for review in sample_reviews: summaries = set() print(review) while len(summaries) < 3: summary = model_infer(model, tokenizer, review + " TL;DR ").split(" TL;DR ")[1].strip() if summary not in summaries: summaries.add(summary) print("Summaries: "+ str(summaries) +"\n") My local coffee shop has me addicted to their 20 oz vanilla chai lattes. At $3.90 a pop I was spending a lot of money. I asked what brand they used, need nutritional information, of course! They told me it was Big Train Chai Vanilla.<br />It's important to follow the directions on the can. I made mine with just milk with a yucky result. Use the water with a little milk as there is milk powder in the mix.<br /><br />WARNING:It's addicting!!! Summaries: {'ADDICTING!!!', 'Addictive!!!', 'Beware!!!'} popcorn is very good. but only makes about half of it.tast so good like moive theater popcorn.so so so goooooooooooooooooood Summaries: {'very good', 'good taste', 'not bad, but not great.'} Love these chips. Good taste,very crispy and very easy to clean up the entire 3 oz. bag in one sitting. NO greasy after-taste. Original and barbecue flavors are my favorites but I haven't tried all flavors. Great product. Summaries: {'very yummy', 'Love these chips!', 'My favorite Kettle chip'} We have not had saltines for many years because of unwanted ingredients. This brand is yummy and contains no unwanted ingredients. It was also a lot cheaper by the case than at the local supermarket. Summaries: {'yummo', 'yummy', 'Great product!'} Best English Breakfast tea for a lover of this variety and I've tried so many including importing it from England. After s 20 year search I've found a very reasonable price for a most falvorful tea. Summaries: {'Wonderful Tea', 'The BEST tea for a lover of a cup of tea', 'Excellent tea for a lover of tea'}

The summaries reflect the content of the review. Feel free to try other reviews to test the capbailities of the model.

In this tutorial, we learned how to fine-tune the Huggingface GPT model to perform Amazon review summarization. The same methodology can be applied to any language model available on https://huggingface.co/models.

Categories: FLOSS Project Planets

ItsMyCode: Python ImportError: No module named PIL Solution

Wed, 2021-12-01 14:51

ItsMyCode |

If you use the Python image library and import PIL, you might get ImportError: No module named PIL while running the project. It happens due to the depreciation of the PIL library. Instead, it would help if you install and use its successor pillow library to resolve the issue.

What is ImportError: No module named PIL?

If you use Python version 3 and try to install and use the PIL library, you will get the ImportError: No module named PIL while importing it, as shown below.

PIL is the Python Imaging Library developed by Fredrik Lundh and Contributors. Currently, PIL is depreciated, and Pillow is the friendly PIL fork by Alex Clark and Contributors. As of 2019, Pillow development is supported by Tidelift.

How to fix ImportError: No module named PIL?

If you are using Python version 3, the best way to resolve this is by uninstalling the existing PIL package and performing a clean installation of the Pillow package, as shown below.

Step 1: Uninstall the PIL package.

pip uninstall PIL

Step 2: Install the Pillow using pip as shown below on different operating systems.

On Windows

python3 -m pip install --upgrade pip python3 -m pip install --upgrade Pillow

On Linux

easy_install Pillow

On OSX  

brew install Pillow

Note: Sometimes, while importing matplotlib in your Jupyter notebook, you might face this issue and doing a standard install of Pillow may not work out. You could do a force install of Pillow, as shown below, to resolve the error.

pip install --upgrade --force-reinstall Pillow pip install --upgrade --force-reinstall matplotlib

Step 3: The most crucial class in the Python Imaging Library is the Image class, and you can import this as shown below.

from PIL import Image im = Image.open("myimage.jpg")

If successful, this function returns an Image object. You can now use instance attributes to examine the file contents:

print(im.format, im.size, im.mode) #Output: PPM (512, 512) RGB

Note: If you use Python version 2.7, you need to install image and Pillow packages to resolve the issue.

python -m pip install image python -m pip install Pillow

The post Python ImportError: No module named PIL Solution appeared first on ItsMyCode.

Categories: FLOSS Project Planets

Python GUIs: Simple multithreading in PyQt/PySide apps with QThreadPool.start() — Easily run Python functions and methods in another thread

Wed, 2021-12-01 11:57

In PyQt5 version 5.15.0 the .start() method of QThreadPool got a new signature that accepts either a Python function, a Python method, or a PyQt/PySide slot. This greatly simplifies the process of running Python code in a separate thread, avoiding the need to create a QRunnable first.

The .start() method schedules the execution of the given function/method/slot on a new thread using the QThreadPool and so avoids blocking your app's main GUI thread. If you have a simple task that you want to execute on another thread, you can now just pass it to .start() and be done with it.

For more information on using a QRunnable for threading, see the multithreading tutorial.

PySide was a little slower to add that signature, but it finally happened in version 6.2.0

To demonstrate how to use .start() to run user-defined Python functions/methods, we'll build a simple GUI with a long-running task.

A bad GUI design

Our demo application is a simple sheep counter which continuously counts upwards from 1. While the sheep are being counted, you can press a button to pick the currently counted sheep. Picking sheep is hard, so this task takes a long time.

This is how the demo GUI app looks like.

If you use PyQt5, make sure that it is of version 5.15.0 or greater, otherwise the demo GUI app won’t work for you.

python import time from PySide6.QtCore import Slot, QTimer from PySide6.QtWidgets import QApplication, QLabel, QMainWindow, QPushButton, QVBoxLayout, QWidget class MainWindow(QMainWindow): def __init__(self, *args, **kwargs): super(MainWindow, self).__init__(*args, **kwargs) self.setFixedSize(250, 100) self.setWindowTitle("Sheep Picker") self.sheep_number = 1 self.timer = QTimer() self.picked_sheep_label = QLabel() self.counted_sheep_label = QLabel() self.layout = QVBoxLayout() self.main_widget = QWidget() self.pick_sheep_button = QPushButton("Pick a sheep!") self.layout.addWidget(self.counted_sheep_label) self.layout.addWidget(self.pick_sheep_button) self.layout.addWidget(self.picked_sheep_label) self.main_widget.setLayout(self.layout) self.setCentralWidget(self.main_widget) self.timer.timeout.connect(self.count_sheep) self.pick_sheep_button.pressed.connect(self.pick_sheep) self.timer.start() @Slot() def count_sheep(self): self.sheep_number += 1 self.counted_sheep_label.setText(f"Counted {self.sheep_number} sheep.") @Slot() def pick_sheep(self): self.picked_sheep_label.setText(f"Sheep {self.sheep_number} picked!") time.sleep(5) # This function represents a long-running task! if __name__ == "__main__": app = QApplication([]) main_window = MainWindow() main_window.show() app.exec() python import time from PyQt6.QtCore import pyqtSlot, QTimer from PyQt6.QtWidgets import QApplication, QLabel, QMainWindow, QPushButton, QVBoxLayout, QWidget class MainWindow(QMainWindow): def __init__(self, *args, **kwargs): super(MainWindow, self).__init__(*args, **kwargs) self.setFixedSize(250, 100) self.setWindowTitle("Sheep Picker") self.sheep_number = 1 self.timer = QTimer() self.picked_sheep_label = QLabel() self.counted_sheep_label = QLabel() self.layout = QVBoxLayout() self.main_widget = QWidget() self.pick_sheep_button = QPushButton("Pick a sheep!") self.layout.addWidget(self.counted_sheep_label) self.layout.addWidget(self.pick_sheep_button) self.layout.addWidget(self.picked_sheep_label) self.main_widget.setLayout(self.layout) self.setCentralWidget(self.main_widget) self.timer.timeout.connect(self.count_sheep) self.pick_sheep_button.pressed.connect(self.pick_sheep) self.timer.start() @pyqtSlot() def count_sheep(self): self.sheep_number += 1 self.counted_sheep_label.setText(f"Counted {self.sheep_number} sheep.") @pyqtSlot() def pick_sheep(self): self.picked_sheep_label.setText(f"Sheep {self.sheep_number} picked!") time.sleep(5) # This function represents a long-running task! if __name__ == "__main__": app = QApplication([]) main_window = MainWindow() main_window.show() app.exec() python import time from PyQt5.QtCore import pyqtSlot, QTimer from PyQt5.QtWidgets import QApplication, QLabel, QMainWindow, QPushButton, QVBoxLayout, QWidget class MainWindow(QMainWindow): def __init__(self, *args, **kwargs): super(MainWindow, self).__init__(*args, **kwargs) self.setFixedSize(250, 100) self.setWindowTitle("Sheep Picker") self.sheep_number = 1 self.timer = QTimer() self.picked_sheep_label = QLabel() self.counted_sheep_label = QLabel() self.layout = QVBoxLayout() self.main_widget = QWidget() self.pick_sheep_button = QPushButton("Pick a sheep!") self.layout.addWidget(self.counted_sheep_label) self.layout.addWidget(self.pick_sheep_button) self.layout.addWidget(self.picked_sheep_label) self.main_widget.setLayout(self.layout) self.setCentralWidget(self.main_widget) self.timer.timeout.connect(self.count_sheep) self.pick_sheep_button.pressed.connect(self.pick_sheep) self.timer.start() @pyqtSlot() def count_sheep(self): self.sheep_number += 1 self.counted_sheep_label.setText(f"Counted {self.sheep_number} sheep.") @pyqtSlot() def pick_sheep(self): self.picked_sheep_label.setText(f"Sheep {self.sheep_number} picked!") time.sleep(5) # This function represents a long-running task! if __name__ == "__main__": app = QApplication([]) main_window = MainWindow() main_window.show() app.exec()

If you run the demo GUI app and you press on the Pick a sheep! button, you’ll notice that for a period of 5 seconds the GUI is completely unresponsive. That's not good.

Have you spotted the problem? The delay comes from the line time.sleep(5) which pauses execution of the Python code for 5 seconds. We've added this to simulate a long-running task – which can be helped by threading! You can experiment by increasing the length of the delay and may notice that your operating system starts complaining about your application not responding.

A good GUI design

So, what can we do to fix our delay issue? Well, this is where the new .start() method of QThreadPool comes in handy!

First, we need to import QThreadPool, so let’s do that.

python from PySide6.QtCore import QThreadPool python from PyQt6.QtCore import QThreadPool python from PyQt5.QtCore import QThreadPool

Next, we need to create a QThreadPool instance. Let’s add

python self.thread_manager = QThreadPool()

to the __init__ block of the MainWindow class.

Now, let’s create a pick_sheep_safely() slot. This new slot will use the .start() method of QThreadPool to call the long-running pick_sheep() slot and move it from the main GUI thread to a completely new thread.

python @Slot() def pick_sheep_safely(self): self.thread_manager.start(self.pick_sheep) # This is where the magic happens! python @pyqtSlot() def pick_sheep_safely(self): self.thread_manager.start(self.pick_sheep) # This is where the magic happens!

Also, make sure that you connect the pick_sheep_safely() slot with the pressed signal of self.pick_sheep_button. So, in the __init__ block of the MainWindow class you should have

python self.pick_sheep_button.pressed.connect(self.pick_sheep_safely)

If you made all those changes, your demo GUI app code should now be:

python import time from PySide6.QtCore import Slot, QThreadPool, QTimer from PySide6.QtWidgets import QApplication, QLabel, QMainWindow, QPushButton, QVBoxLayout, QWidget class MainWindow(QMainWindow): def __init__(self, *args, **kwargs): super(MainWindow, self).__init__(*args, **kwargs) self.setFixedSize(250, 100) self.setWindowTitle("Sheep Picker") self.sheep_number = 1 self.timer = QTimer() self.picked_sheep_label = QLabel() self.counted_sheep_label = QLabel() self.layout = QVBoxLayout() self.main_widget = QWidget() self.thread_manager = QThreadPool() self.pick_sheep_button = QPushButton("Pick a sheep!") self.layout.addWidget(self.counted_sheep_label) self.layout.addWidget(self.pick_sheep_button) self.layout.addWidget(self.picked_sheep_label) self.main_widget.setLayout(self.layout) self.setCentralWidget(self.main_widget) self.timer.timeout.connect(self.count_sheep) self.pick_sheep_button.pressed.connect(self.pick_sheep_safely) self.timer.start() @Slot() def count_sheep(self): self.sheep_number += 1 self.counted_sheep_label.setText(f"Counted {self.sheep_number} sheep.") @Slot() def pick_sheep(self): self.picked_sheep_label.setText(f"Sheep {self.sheep_number} picked!") time.sleep(5) # This function doesn't affect GUI responsiveness anymore... @Slot() def pick_sheep_safely(self): self.thread_manager.start(self.pick_sheep) # ...since it is called by this start() method if __name__ == "__main__": app = QApplication([]) main_window = MainWindow() main_window.show() app.exec() python import time from PyQt6.QtCore import pyqtSlot, QThreadPool, QTimer from PyQt6.QtWidgets import QApplication, QLabel, QMainWindow, QPushButton, QVBoxLayout, QWidget class MainWindow(QMainWindow): def __init__(self, *args, **kwargs): super(MainWindow, self).__init__(*args, **kwargs) self.setFixedSize(250, 100) self.setWindowTitle("Sheep Picker") self.sheep_number = 1 self.timer = QTimer() self.picked_sheep_label = QLabel() self.counted_sheep_label = QLabel() self.layout = QVBoxLayout() self.main_widget = QWidget() self.thread_manager = QThreadPool() self.pick_sheep_button = QPushButton("Pick a sheep!") self.layout.addWidget(self.counted_sheep_label) self.layout.addWidget(self.pick_sheep_button) self.layout.addWidget(self.picked_sheep_label) self.main_widget.setLayout(self.layout) self.setCentralWidget(self.main_widget) self.timer.timeout.connect(self.count_sheep) self.pick_sheep_button.pressed.connect(self.pick_sheep_safely) self.timer.start() @pyqtSlot() def count_sheep(self): self.sheep_number += 1 self.counted_sheep_label.setText(f"Counted {self.sheep_number} sheep.") @pyqtSlot() def pick_sheep(self): self.picked_sheep_label.setText(f"Sheep {self.sheep_number} picked!") time.sleep(5) # This function doesn't affect GUI responsiveness anymore... @pyqtSlot() def pick_sheep_safely(self): self.thread_manager.start(self.pick_sheep) # ...since it is called by this start() method if __name__ == "__main__": app = QApplication([]) main_window = MainWindow() main_window.show() app.exec() python import time from PyQt5.QtCore import pyqtSlot, QThreadPool, QTimer from PyQt5.QtWidgets import QApplication, QLabel, QMainWindow, QPushButton, QVBoxLayout, QWidget class MainWindow(QMainWindow): def __init__(self, *args, **kwargs): super(MainWindow, self).__init__(*args, **kwargs) self.setFixedSize(250, 100) self.setWindowTitle("Sheep Picker") self.sheep_number = 1 self.timer = QTimer() self.picked_sheep_label = QLabel() self.counted_sheep_label = QLabel() self.layout = QVBoxLayout() self.main_widget = QWidget() self.thread_manager = QThreadPool() self.pick_sheep_button = QPushButton("Pick a sheep!") self.layout.addWidget(self.counted_sheep_label) self.layout.addWidget(self.pick_sheep_button) self.layout.addWidget(self.picked_sheep_label) self.main_widget.setLayout(self.layout) self.setCentralWidget(self.main_widget) self.timer.timeout.connect(self.count_sheep) self.pick_sheep_button.pressed.connect(self.pick_sheep_safely) self.timer.start() @pyqtSlot() def count_sheep(self): self.sheep_number += 1 self.counted_sheep_label.setText(f"Counted {self.sheep_number} sheep.") @pyqtSlot() def pick_sheep(self): self.picked_sheep_label.setText(f"Sheep {self.sheep_number} picked!") time.sleep(5) # This function doesn't affect GUI responsiveness anymore... @pyqtSlot() def pick_sheep_safely(self): self.thread_manager.start(self.pick_sheep) # ...since it is called by this start() method if __name__ == "__main__": app = QApplication([]) main_window = MainWindow() main_window.show() app.exec()

Now, if you press on the Pick a sheep! button the pick_sheep method is executed in a separate thread and does not block the main GUI thread. Your application will remain responsive, and the sheep counting will continue normally -- even though it still has to complete a long-running task in the background.

Try increasing the length of the delay now – for example, sleep(10) – and you'll notice that it has no effect on the responsiveness of the UI.

Conclusion

And that’s it! I hope you’ll find this new .start() method of QThreadPool useful in any of your PyQt/PySide GUI apps that have some kind of a long-running task to be performed while the app’s main GUI thread is running.

For an in-depth guide to building Python GUIs with PySide6 see my book, Create GUI Applications with Python & Qt6.

Categories: FLOSS Project Planets

PyCharm: Introducing PyCharm 2021.3!

Wed, 2021-12-01 10:40

We’ve been working hard to deliver features in PyCharm that will make you more productive and your coding smoother. This release cycle introduces Poetry support, the new FastAPI project type, the Beta version of our remote development support, a redesigned Jupyter notebook experience, and much more!

Download PyCharm 2021.3

In this blog post, we will go through some of the highlights.

Poetry Support

Poetry is becoming more and more popular among Python developers, and there were a lot of issues reported to our tracker to add support for it. The good news for Poetry users (and for those wanting to try it) is that PyCharm now supports Poetry out of the box. But that’s is not all! We’ve also bundled the TOML plugin so that you also get code completion for your pyproject.toml file.

This feature was made possible by merging the plugin created by Koudai Aono into the PyCharm source code. Thank you Koudai for all your hard work!

FastAPI Support [Pro]

FastAPI is a popular, high-performance, Python web framework for building APIs, and PyCharm Pro now offers support for it as a project and run configuration type.

To create a new FastAPI project, select the FastAPI project type and let PyCharm install its dependencies and create the run/debug configurations for you.

Alternatively, you can also open an existing FastAPI project with PyCharm Pro, let PyCharm handle creating the virtual environment for you, and create a FastAPI run configuration yourself. PyCharm will then detect your application and run Uvicorn for you.

When working with endpoints in FastAPI, you will frequently need to test them to ensure that everything is working as expected. In PyCharm Pro you can do this from the comfort of your editor using the HTTP Client integration.

Just open the “file_name.http” file (already present for new FastAPI projects created using the PyCharm wizard) and use it to send requests to your application endpoints. You can read more about this in the documentation.

New Endpoints Tool Window for FastAPI and Flask [Pro]

If you develop APIs, we also have a great new feature to help you manage your endpoints. PyCharm Pro will scan FastAPI and Flask project routes and list them in the new Endpoints tool window, where you can have an overview of all your URLs, as well as code completion, navigation, and refactoring capabilities. The Endpoints tool window also displays documentation for each endpoint and allows you to test it using the HTTP client.

New Jupyter Notebook Experience [Pro]

Our team has been working hard to improve PyCharm for software engineers working in the data science sphere. PyCharm Pro 2021.3 comes with new and improved support for Jupyter notebooks.


Jupyter support in PyCharm Pro is powered by DataSpell, our new IDE designed for professional data scientists. Are you a data scientist? Try DataSpell now! New Notebook UI

For starters, PyCharm Pro now comes with support for the classic Jupyter notebook user interface out of the box, including full compatibility with its popular shortcuts.

Interactive Outputs

We’ve also added full support for both static and JavaScript-based outputs used by popular scientific libraries such as Plotly, Bokeh, Altair, ipywidgets, and others, as well as rich support for DataFrames, that you can explore in situ, or open in a dedicated tab.

IDE capabilities

Having Jupyter support inside the IDE has its perks. It means that you get to benefit from all of the powerful PyCharm tools such as auto import, code completion, debugging and refactoring capabilities, and more in your Jupyter notebooks. To debug inside a Jupyter notebook, just add a breakpoint and run the cell under the debugger.

Remote development Beta [Pro]

Remote development support has also been a commonly requested feature from our users, and 2021.3 brings beta support for it. PyCharm users can now connect to remote machines from anywhere in the world, run PyCharm’s backend, and take advantage of remote computing power while feeling that everything is running locally.

To try it out, just click Remote Development on the Welcome screen, select the SSH option and follow the wizard to provide your credentials, establish the connection, download the IDE on the server, and open your remote project in PyCharm. You can read the documentation for more details.

This feature is still in Beta, and your feedback on it is highly appreciated.

User experience

We have also been working to improve the overall PyCharm user experience. Some of the highlights include:

Feature trainer: New onboarding tour and a series of Git lessons

For users who are new to PyCharm or just want a refresher on how to use it, the IDE feature trainer now comes with an onboarding tour and new lessons. Trying it out is as easy as clicking ‘Learn PyCharm’ on the Welcome screen or clicking Help | Learn IDE in the main menu in the IDE.

Reorganized Version Control Settings

We’ve reorganized the VCS settings and made them more discoverable. In Preferences / Settings | Version Control you will now find a list of all the available settings, serving as a starting point for configuring your VCS. The settings inside the sections are now organized by the most important processes: Commit, Push, and Update.

Data editor Aggregate view [Pro]

We’ve implemented an Aggregate view for ranges of cells. This highly anticipated feature will go a long way towards helping you manage your data by taking away the burden of writing additional queries! It also makes the data editor easier to use, bringing it a step closer to Microsoft Excel and Google Sheets.

To use this feature you will first need to select the cell range you want to see the view for, then right-click and select Show Aggregate View from the menu.

End of support for Mako, Buildout, and Web2Py

As announced in our previous release (2021.2 announcements), from PyCharm 2021.3 onwards there will no longer be support for Mako, Buildout, or Web2Py.

These are all the features I’d like to highlight for this release. If you want to read more about the other features included in this release check out our What’s New page or read the release notes for the full list of features implemented and bugs fixed.

As always, your feedback is highly appreciated. Feel free to share it with us on Twitter (@pycharm), or by reporting any bugs you encounter to our tracker.

Happy coding!

The PyCharm team

Categories: FLOSS Project Planets

Python for Beginners: Preorder Tree Traversal Algorithm in Python

Wed, 2021-12-01 09:23

Binary trees are very useful in representing hierarchical data. In this article, we will discuss how to print all the elements in a binary tree in python. For this, we will use the preorder tree traversal algorithm. We will also implement the preorder tree traversal in python.

What is the Preorder tree traversal ?

Preorder tree traversal is a depth first traversal algorithm. Here, we start from a root node and traverse a branch of the tree until we reach the end of the branch. After that, we move to the next branch. This process continues until all the nodes in the tree are printed. 

The preorder tree traversal algorithm gets its name from the order in which the nodes of a tree are printed. In this algorithm, we first print a node. After that, we print the left child of the node. And, at last, we print the right child of the node. This process is recursive in nature. Here, the right child of a node is only printed when all the nodes in the left subtree of the current node and the current node itself have already been printed.  

Let us understand the process using the binary tree given in the following image.

Binary Tree

Let us print all of the nodes in the above binary tree using the preorder traversal.

  • First, we will start from the root node and print its value i.e. 50.
  • After that we have to print the left child of 50. So, we will print 20. 
  • After printing 20, we have to print the left child of 20. So, we will print 11.
  • 11 has no children. So, we will move to node 20 and print its right child i.e. we will print 22.
  • 22 has no children so, we will move to 20. Again all of the children of 20 have been printed. So, we will move to 50. At 50, we will print its right child as all the nodes in its left subtree have already been printed. Hence, we will print 53.
  • After printing 53, we have to print the left child of 53. So, we will print 52.
  • 52 has no children. So, we will move to node 53 and print its right child i.e. we will print 78.
  • At this point, we have printed all of the nodes in the binary tree. So, we will terminate the process.

You can observe that we have printed the values in the order 50, 20, 11,22, 53, 52, 78. Let us now formulate an algorithm for the preorder tree traversal .

Algorithm for preorder tree traversal

As you have an overview of the entire process, we can formulate the algorithm for preorder tree traversal as follows.

  1. Start from the root node.
  2. If the root is empty, goto 6.
  3. Print the root node.
  4. Traverse the left subtree recursively.
  5. Traverse the right subtree recursively.
  6. Stop.
Implementation of preorder tree traversal in Python

 As we have discussed the algorithm for preorder tree traversal and its working, Let us implement the algorithm and execute it for the binary tree given in the above image.

class BinaryTreeNode: def __init__(self, data): self.data = data self.leftChild = None self.rightChild = None def preorder(root): # if root is None,return if root is None: return # print the current node print(root.data, end=" ,") # traverse left subtree preorder(root.leftChild) # traverse right subtree preorder(root.rightChild) def insert(root, newValue): # if binary search tree is empty, create a new node and declare it as root if root is None: root = BinaryTreeNode(newValue) return root # if newValue is less than value of data in root, add it to left subtree and proceed recursively if newValue < root.data: root.leftChild = insert(root.leftChild, newValue) else: # if newValue is greater than value of data in root, add it to right subtree and proceed recursively root.rightChild = insert(root.rightChild, newValue) return root root = insert(None, 50) insert(root, 20) insert(root, 53) insert(root, 11) insert(root, 22) insert(root, 52) insert(root, 78) print("Preorder traversal of the binary tree is:") preorder(root)

Output:

Preorder traversal of the binary tree is: 50 ,20 ,11 ,22 ,53 ,52 ,78 ,

You can observe that the code gives the same output that we have derived while discussing this algorithm.

Conclusion

In this article, we have discussed and implemented the preorder tree traversal algorithm in Python. To learn more about other tree traversal algorithms, you can read this article on In order tree traversal in Python and Level order tree traversal in python.

The post Preorder Tree Traversal Algorithm in Python appeared first on PythonForBeginners.com.

Categories: FLOSS Project Planets

Real Python: Advent of Code: Solving Your Puzzles With Python

Wed, 2021-12-01 09:00

Advent of Code is an online Advent calendar where you’ll find new programming puzzles offered each day from December 1st to the 25th. While you can solve the puzzles at any time, the excitement when new puzzles unlock is really something special. You can participate in Advent of Code in any programming language—including Python!

This tutorial will help you get started with solving puzzles and earning your first golden stars.

In this tutorial, you’ll learn:

  • What an online Advent calendar is
  • How solving puzzles can advance your programming skills
  • How you can participate in the Advent of Code
  • How you can organize your code and tests when solving Advent of Code puzzles
  • How test-driven development can be used when solving puzzles

Advent of Code puzzles are designed to be approachable by anyone with an interest in problem-solving. You don’t need a heavy computer science background to participate. Instead, Advent of Code is a great arena for learning new skills and testing out new features of Python.

Free Bonus: Click here to get a Python Cheat Sheet and learn the basics of Python 3, like working with data types, dictionaries, lists, and Python functions.

Puzzling in Programming?

Working on puzzles may seem like a waste of your available programming time. After all, it seems like you’re not really producing anything useful and you’re not advancing your current projects forward.

However, there are several advantages to taking some time off to practice with programming puzzles:

  • Programming puzzles are usually better specified and more contained than your regular job tasks. They offer you the chance to practice logical thinking on problems that are less complex than the ones you typically need to handle in your day job.

  • You can often challenge yourself with several similar puzzles. This allows you to build procedural memory, much like muscle memory, and get experience with structuring certain kinds of code.

  • Puzzles are often designed with an eye towards a solution. They allow you to learn about and apply algorithms that are tried and tested and are an important part of any programmer’s toolbox.

  • For some puzzle solutions, even the greatest supercomputers can be too slow if the algorithm is inefficient. You can analyze the performance of your solution and get experience to help you understand when a straightforward method is fast enough and when a more optimized procedure is necessary.

  • Most programming languages are well-suited for solving programming puzzles. This gives you a great opportunity to compare different programming languages for different tasks. Puzzles are also a great way for getting to know a new programming language or trying out some of the newest features of your favorite language.

On top of all of this, challenging yourself with a programming puzzle is often pretty fun! When you add it all up, setting aside some time for puzzles can be very rewarding.

Exploring Options for Solving Programming Puzzles Online

Luckily, there are many websites where you can find programming puzzles and try to solve them. There are often differences in the kinds of problems these websites present, how you submit your solutions, and what kind of feedback and community the sites can offer. You should therefore take some time to look around and find those that appeal the most to you.

In this tutorial, you’ll learn about Advent of Code, including what kind of puzzles you can find there and which tools and tricks you can employ to solve them. However, there are also other places where you can get started solving programming puzzles:

  • Exercism has learning tracks in many different programming languages. Each learning track offers small tutorials about different programming concepts, coding challenges, and mentors that give you feedback on your solutions.

  • Project Euler has been around for a long time. The site offers hundreds of puzzles, usually formulated as math problems. You can solve the problems in any programming language, and once you’ve solved a puzzle, you get access to a community thread where you can discuss your solution with others.

  • Code Wars offers tons of coding challenges, which they call katas. You can solve puzzles in many different programming languages with their built-in editor and automated tests. Afterward, you can compare your solutions to others’ and discuss strategies in the forums.

  • HackerRank has great features if you’re looking for a job. They offer certifications in many different skills, including problem-solving and Python programming, as well as a job board that lets you show off your puzzle-solving skills as part of your job applications.

There are many other sites available where you can practice your puzzle-solving skills. In the rest of this tutorial, you’ll focus on what Advent of Code has to offer.

Preparing for Advent of Code: 25 Fresh Puzzles for Christmas

It’s time for Advent of Code! It was started by Eric Wastl in 2015. Since then, a new advent calendar of twenty-five new programming puzzles has been published every December. The puzzles have gotten more and more popular over the years. More than 170,000 people have solved at least one of the puzzles from 2020.

Note: Traditionally, an Advent calendar is a calendar used to count the days of Advent while waiting for Christmas. Over the years, Advent calendars have become more commercial and have lost some of their Christian connection.

Most Advent calendars start on December 1st and end on December 24th, Christmas Eve, or December 25th, Christmas Day. Nowadays, there are all kinds of Advent calendars available, including LEGO calendars, tea calendars, and cosmetics calendars.

In traditional Advent calendars, you open one door every day to reveal what’s inside. Advent of Code mimics this by letting you open one puzzle each day from December 1st to December 25th. For each puzzle you solve, you’ll earn golden stars that are yours to keep.

In this section, you’ll get more familiar with Advent of Code and see a glimpse of your first puzzle. Later, you’ll look at the details of how you can solve these puzzles and practice solving a few of the puzzles yourself.

Advent of Code Puzzles

Advent of Code is an online Advent calendar where a new puzzle is published every day from December 1st to December 25th. Each puzzle becomes available at midnight, US Eastern Time. An Advent of Code puzzle has a few typical characteristics:

  • Each puzzle consists of two parts, but the second part isn’t revealed until you finish the first part.
  • You’ll earn one golden star (⭐) for each part that you finish. This means you can earn two stars per day and fifty stars if you solve all the puzzles for one year.
  • The puzzle is the same for everyone, but you need to solve it based on personalized input that you get from the Advent of Code site. This means that your answer to a puzzle will be different from someone else’s, even if you use the same code to calculate it.

You can participate in a global race to be the first to solve each puzzle. However, this is usually pretty crowded with highly skilled, competitive programmers. Advent of Code is probably going to be more fun if you use it as practice for yourself or if you challenge your friends and coworkers to a small, friendly competition.

Read the full article at https://realpython.com/python-advent-of-code/ »

[ 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 ]

Categories: FLOSS Project Planets

Codementor: Best Free And Paid Air Quality API 2022

Wed, 2021-12-01 07:26
APIs for air quality may be used to detect air pollution, carbon monoxide, and the air quality index, among other things. You may get current, projected, and historical information. These APIs may be used to monitor the levels of key air pollutants from a variety of data sources.
Categories: FLOSS Project Planets

Tryton News: Newsletter December 2021

Wed, 2021-12-01 02:00

After release 6.2 we have already resumed development with some cleaning and performance improvements.

Changes for the User

The early planning for stock quantities now takes internal incoming requests into account.

You can now define a delay after which an email notification will be sent.

The reset password email now displays how long it is valid instead of the UTC expiry date and time.

The record names for addresses now contains all the street lines instead of just the first one.

Changes for the System Administrator

It is now possible to send test emails without a database.

Changes for the Developer

The PostgreSQL back-end now uses the JSONB type by default to store the value of Dict fields.

We activated support for window functions when using SQLite versions greater than 3.25.0.

We use RENAME and DROP COLUMN when using SQLite versions that support them.

It is now possible to customize the states of the shipments with which a sale can be grouped.

The button to generate SEPA messages has been prefixed by sepa avoiding any name clashes with other modules.

It is possible to mark the getter of a Function field as not depending on the context. By doing this it can be stored in the transaction cache in readonly transactions.

The cache of instances passed to Function field getters are now prefilled with data already calculated for the instance. The order in which the Function fields are called can be tuned to take advantage of this behavior when the calculations depend on other Function fields from the same record.

1 post - 1 participant

Read full topic

Categories: FLOSS Project Planets

PyCoder’s Weekly: Issue #501 (Nov. 30, 2021)

Tue, 2021-11-30 14:30

#501 – NOVEMBER 30, 2021
View in Browser »

Late-Bound Argument Defaults for Python

Python supports default values for arguments to functions, but those defaults are evaluated at function-definition time. A proposal to add defaults that are evaluated when the function is called has been discussed at some length on the python-ideas mailing list.
JAKE EDGE

Data Visualization Interfaces in Python With Dash

In this course, you’ll learn how to build a dashboard using Python and Dash. Dash is a framework for building data visualization interfaces. It helps data scientists build fully interactive web applications quickly.
REAL PYTHON course

Application Performance Monitoring Built for Developers, by Developers

Scout is a lightweight, production-grade application monitoring service built for modern development teams. Proactive alerting, real-time insight and always-on support means you can rest easy knowing Scout will find performance issues before your customers do. Embed our agent, and we’ll do the rest →
SCOUT APM sponsor

Rats in Doom: A Novel VR Setup for Rodents

A novel VR setup developed for rodents that lets rats play Doom. Uses Python for the controller interface.
VIKTOR TÓTH

CPython Dev in Residence: Weekly Report, November 22–28

A short review of try/except, exception handling in asyncio today, and the future of asyncio error handling.
ŁUKASZ LANGA

Discussions Python 3.10 Pattern Matching: Wildcard in String?

STACK OVERFLOW

Does NumPy Array Really Take Less Memory Than Python List?

STACK OVERFLOW

Python Jobs Senior Python Developer (Anywhere)

Six Feet Up

Senior Backend Engineer (Anywhere)

BMAT

Senior Backend Software Engineer (Anywhere)

Clay

Senior Python Engineer (Anywhere)

Flashpoint

Senior Software Engineer (United States)

Tomo

Full Stack Software Engineer (Washington D.C., USA)

Quorum

Senior Software Engineer (Washington D.C., USA)

Quorum

Python Backend Engineer (Hasselt, Belgium)

madewithlove

More Python Jobs >>>

Articles & Tutorials Programmers Should Stop Celebrating Incompetence

The creator of Ruby on Rails on programmer competence: “The world has never had a greater need for programmers than it does today. It’s never had a greater need for competent programmers than it does today. Let’s skip the overly self-deprecating nonsense that nobody knows what they’re doing, and trying to learn things in depth is not for us.”
DAVD HEINEMEIER HANSSON opinion

How to Ditch Codecov for Python Projects

“Codecov’s unreliability breaking CI on my open source projects has been a constant source of frustration for me for years. I have found a way to enforce coverage over a whole GitHub Actions build matrix that doesn’t rely on third-party services.”
HYNEK SCHLAWACK

Get Your Next Python Job Through Hired

Hired is home to thousands of companies ranging from startups to Fortune 500s that are actively hiring developers, data scientists, mobile engineers, and more. Its really easy: once you create a profile, hiring managers can send interview requests based on your skills. Sign up today →
HIRED sponsor

Ready to Publish Your Python Packages?

Are you interested in sharing your Python project with the broader world? Would you like to make it easily installable using pip? How do you create Python packages that share your code in a scalable and maintainable way?
REAL PYTHON podcast

How to Write a Great Stack Overflow Question

“The single best thing you can do when asking for coding help online is provide a short, complete example script that others can copy, paste, and run without any modification to reproduce your problem.”
KEVIN MARKHAM • Shared by Kevin Markham

Experimental APIs in Python 3.10 and the Future of Trust Stores

“In Python 3.10.0 there were a few new APIs added to the ssl module related to certificate chains that weren’t listed in the Python 3.10 release notes due to being experimental.”
SETH MICHAEL LARSON

The Problem With Python’s map and filter (And How We Might Fix It)

The author explores the pros and cons of Python’s default map() and filter() implementation and potential improvements that could be made.
ABHINAV OMPRAKASH • Shared by Abhinav

Shortcut Provides Speedy Task Management, Reporting, and Collaboration for Software Teams

Shortcut is project management built for developers. Whether you’re a startup that iterates quickly by providing every engineer with a free pallet of Red Bull, or a large org that has strict ship dates to hit, give us a try for free.
SHORTCUT sponsor

The Rinds of the Cheese Shop Menu

A silly analysis of the weird and wonderful contents of PyPI: What are the longest package names? Numeric vs non-numeric version names?
BEN NUTTALL • Shared by Ben Nuttall

Financial Market Data Analysis With Pandas

MATTHEW WRIGHT

Introduction to Python’s operator Module

FLORIAN DAHLITZ • Shared by Florian Dahlitz

Projects & Code pyc64: Commodore-64 Simulator in Pure Python

GITHUB.COM/IRMEN

tiptop: Command-Line System Monitoring

GITHUB.COM/NSCHLOE

myhdl: Python as a Hardware Description Language

GITHUB.COM/MYHDL

RexMex: Recommender System Evaluation Library

GITHUB.COM/ASTRAZENECA • Shared by Benedek Rozemberczki

kolo: See Everything Happening in Your Running Django App

GITHUB.COM/KOLOFORDJANGO • Shared by Philipp Acsany

SQLLineage: SQL Lineage Analysis Tool

GITHUB.COM/REATA • Shared by Ryan Hu

FastAPI-Azure-Auth: Azure AD Auth for FastAPI Apps

INTILITY.GITHUB.IO • Shared by Jonas Krüger Svensson

Events Weekly Real Python Office Hours Q&A (Virtual)

December 1, 2021
REALPYTHON.COM

FlaskCon 2021 Online

December 1 to December 5, 2021
FLASKCON.COM

PyCon Tanzania

December 1 to December 6, 2021
PYCON.OR.TZ

PyCode Conference

December 2 to December 4, 2021
PYCODE-CONFERENCE.ORG

Pyjamas Conf 2021

December 4 to December 6, 2021
PYJAMAS.LIVE

PyCon Indonesia 2021

December 4 to December 6, 2021
PYCON.ID

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

[ 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 ]

Categories: FLOSS Project Planets

STX Next: Python Outsourcing: A Short Guide for CTOs and Technical Managers

Tue, 2021-11-30 13:49

If we could distill Python’s main advantage over other programming languages into just one word, it would be: “simplicity.”

Categories: FLOSS Project Planets

Ching-Hwa Yu: How to Create a Python Plugin System with Stevedore

Tue, 2021-11-30 13:00
Photo by Kieran Wood on Unsplash

One of the questions that I see and hear often is how to extend applications using a Python plugin system. For a test engineer, this is usually related to hardware abstraction. For others, they may want to separate the core functionality from extensions. Through this method, deployment can be simplified where only the required pieces are installed through their individual package(s). Whatever the reason may be, several libraries are available to tackle this challenge. In this article, a simple abstraction layer will be built using the Stevedore library and we will cover the the main concepts of building plugins.

The code in this article is available at https://github.com/chinghwayu/plugin_tutorial.

NOTE: While the code illustrates relays and a hardware abstraction layer, the same concept can be used for services such as a database with a software abstraction layer.

Plugin Architecture

Regardless of the plugin framework used, the architecture behind the implementation of plugins is mostly the same.

  • Define abstract base class
  • Define plugin class inheriting from base class
Abstract Base Class

For plugins of similar type in a Python plugin system, there usually is some common functionality. Plugins based on a protocol or specification typically have common basic functionality. For example, instruments that adhere to IEEE 488.2 standard must respond to queries for its identification.

Although the abstract part is sometimes omitted, this is an important step as it establishes the basic structure of each plugin by defining which methods must be implemented. In Python, this is accomplished with the abc module.

The example shown defines a basic relay instrument driver with three methods – connect, disconnect, and reconnect. In the __init__ method, the connected attribute is established for status as this is common between all plugins.

For the other abstract methods, only docstrings are needed. There is no need to include pass or other code.

from abc import ABCMeta, abstractmethod class RelayBase(metaclass=ABCMeta): """Base class for relay plugins""" def __init__(self) -> None: """Define base attributes.""" self.connected = False @abstractmethod def disconnect(self) -> None: """Disconnects relay.""" @abstractmethod def connect(self) -> None: """Connects relay.""" @abstractmethod def reconnect(self, seconds: int) -> None: """Disconnects for specified time and reconnects. Args: seconds (int): Amount of time to sleep between disconnect and connect. """ Plugin Class

When defining the actual implementation, each of the plugins will inherit from the plugin base class. In the example, two plugins are defined that inherit from RelayBase.

In the __init__ method, a super() call is made to create the connected attribute which the other methods will update.

class RelayOne(RelayBase): def __init__(self): super().__init__() def disconnect(self): self.connected = False print("Disconnected One") def connect(self): self.connected = True print("Connected One") def reconnect(self, seconds: int = 5): self.seconds = seconds self.disconnect() print(f"One paused for {seconds} seconds...") self.connect() class RelayTwo(RelayBase): def __init__(self): super().__init__() def disconnect(self): self.connected = False print("Disconnected Two") def connect(self): self.connected = True print("Connected Two") def reconnect(self, seconds: int = 5): self.seconds = seconds self.disconnect() print(f"Two paused for {seconds} seconds...") self.connect() Loading Plugins

At this point, you may think that this is all that’s needed to establish a Python plugin system. For simple plugins, this may be true. However, consider the following:

  • How do we decide which plugin to call at runtime?
  • How can we easily switch between the implementations?
  • How can we package these plugins for distribution?
  • How can we test the interfaces to ensure the correct implementation is being called?

For simple applications or scripts, we may simply call the specific implementation directly and hardcode this in. But consider the case where you may be sharing code with a teammate in another location and they don’t have the same relay. We don’t want to maintain another version of the same code with the alternate implementation hardcoded. What we need is way to easily switch between implementations without altering any code. The only change that should be made is in a configuration file for which implementation to use at runtime.

Plugin Entry Point

There are several ways to discover and load plugins. With Stevedore, this uses entry points to establish keys that can be queried as pointers to the location of specific code. This is the same mechanism found often in packages that enable the launching of Python code as command line scripts once installed into an environment. While this uses a built in console_scripts type of entry point, custom entry point types can be created for the purpose of managing plugins.

For a full discussion on extending applications with plugins, please watch the PyCon 2013 talk on this subject from the author of Stevedore, Doug Hellman. The presentation compares the approach taken with Stevedore compared to other existing approaches at the time.

When building packages for distribution, we can add entry points so that when it’s installed into a Python environment, the environment immediately knows where the plugins are located from the established keys. Adding entry points is simple. In the setup.py for a package, assign a dictionary to the entry_points parameter of setup.

from setuptools import setup setup( entry_points={ "plugin_tutorial": [ "relay1 = relay:RelayOne", "relay2 = relay:RelayTwo", ], }, )

The plugin_tutorial key is used as the plugin namespace. The names for each plugin is defined as relay1 and relay2. The location of the the plugin is defined as the module name and class within the module separated by colon, relay:RelayOne and relay:RelayTwo.

For cases when we are using plugins but don’t need to install as package, we can register them into the entry point cache of Stevedore. This is useful for development purposes and when implementing unit tests.

The example below checks a namespace for the specified entry point. If the entry point doesn’t exist, it will be added.

View this gist on GitHubRegisters a stevedore plugin dynamically without needing to install as a package Managing Plugins

With Stevedore, there are several ways to manage plugins in a Python plugin system.

  • Drivers – Single Name, Single Entry Point
  • Hooks – Single Name, Many Entry Points
  • Extensions – Many Names, Many Entry Points

For this article, the driver approach will be discussed since that is the most common use case. Take a look at the Stevedore documentation that discuss Patterns for Loading for the other methods.

For a driver, we need to call the DriverManager. In the parameter list, only namespace and name are required which are directly related to the entry points. Optional parameters are available and the one used in this example is invoke_on_load. While the relay example only establishes a class attribute, for an actual instrument driver, we usually need to perform some kind of initialization. This can be executed at the time when the plugin is loaded.

Calling DriverManager will return a manager object. The actual driver object can be accessed through the driver property. From this property, we can also create abstracted methods to call the driver methods.

from stevedore import driver class Relay: def __init__(self, name="", **kwargs) -> None: self._relay_mgr = driver.DriverManager( namespace="plugin_tutorial", name=name, invoke_on_load=True, invoke_kwds=kwargs, ) @property def driver(self): return self._relay_mgr.driver def disconnect(self) -> None: self.driver.disconnect() def connect(self) -> None: self.driver.connect() def reconnect(self, seconds: int = 5) -> None: self.driver.reconnect(seconds)

The **kwargs parameter is not used but included to show implementation of how to pass parameters to drivers which may have different initialization parameters.

The @property decorator for the driver method is syntactic sugar to provide a shortcut to the driver object. If this wasn’t provided, we would need to call the driver’s disconnect method as:

r = Relay(name="relay1") r._relay_mgr.driver.disconnect() Putting It Together

For a plugin installed into a Python environment, the entry points have established when the package was installed. Through the abstraction interface, we can decide which plugin to load at runtime. Shown is a unit test that calls both plugins and each of its methods.

In order to run this, we will need to first install as a package.

$ pip install -e /path/to/plugin_tutorial ... Installing collected packages: plugin-tutorial Running setup.py develop for plugin-tutorial Successfully installed plugin-tutorial $ pip list | grep plugin_tutorial plugin-tutorial 1.0.0 /path/to/plugin_tutorial from relay import Relay def test_installed_plugin(): r1 = Relay(name="relay1") assert isinstance(r1, Relay) assert r1.driver.connected == False r1.disconnect() assert r1.driver.connected == False r1.connect() assert r1.driver.connected == True r1.reconnect(7) assert r1.driver.seconds == 7 r2 = Relay(name="relay2") assert isinstance(r2, Relay) assert r2.driver.connected == False r2.disconnect() assert r2.driver.connected == False r2.connect() assert r2.driver.connected == True r2.reconnect(9) assert r2.driver.seconds == 9

To call plugins not installed through the package installation process, we’ll need to first register and then call the plugins. This is useful for writing unit tests that include a dummy plugin. Shown is the same unit test with the plugin registered.

from relay import Relay from register_plugin import register_plugin def test_register_plugin(): namespace = "plugin_tutorial" register_plugin( name="relay1", namespace=namespace, entry_point="relay:RelayOne", ) register_plugin( name="relay2", namespace=namespace, entry_point="relay:RelayTwo", ) r1 = Relay(name="relay1") assert isinstance(r1, Relay) assert r1.driver.connected == False r1.disconnect() assert r1.driver.connected == False r1.connect() assert r1.driver.connected == True r1.reconnect(7) assert r1.driver.seconds == 7 r2 = Relay(name="relay2") assert isinstance(r2, Relay) assert r2.driver.connected == False r2.disconnect() assert r2.driver.connected == False r2.connect() assert r2.driver.connected == True r2.reconnect(9) assert r2.driver.seconds == 9 Resources

For additional information:

The post How to Create a Python Plugin System with Stevedore appeared first on Ching-Hwa Yu.

Categories: FLOSS Project Planets

Python for Beginners: Shortest Path Length from a Vertex to other Vertices in a Graph

Tue, 2021-11-30 12:56

Graphs are used to represent geographical maps, computer networks, etc. In this article, we will discuss how to calculate the shortest distance between vertices in an unweighted graph. To calculate the shortest path length from a vertex to other vertices, we will use breadth first search algorithm.

How to calculate the Shortest Path Length from a Vertex to other vertices?

In an unweighted graph, all the edges have equal weight. It means that we just have to count the number of edges between each vertex to calculate the shortest path length between them. 

For example, consider the following graph.

Graph in Python

Let us calculate the shortest distance between each vertex in the above graph.

There is only one edge E2 between vertex A and vertex B. So, the shortest path length between them is 1. 

We can reach C from A in two ways. The first one is using the edges E4-> E5->E6 and the second path is using the edges E2-> E6. Here, we will choose the shortest path, i.e. E2-> E6. Hence the shortest path length between vertex A and vertex C is 2.

There is only one edge E1 between vertex A and vertex D. So, the shortest path length between them is 1. 

There is only one edge E3 between vertex A and vertex E. So, the shortest path length between them is 1. 

We can reach F from A in two ways. The first one is using the edges E2-> E5 and the second path is using the edges E4. Here, we will choose the shortest path, i.e. E4. Hence the shortest path length between vertex A and vertex F is 1.

Algorithm to calculate the Shortest Path Length from a Vertex to other vertices

By now, you must have understood that we have to count the number of edges between the vertices to calculate the distance between the vertices. For this, we will modify the  breadth first search algorithm as follows.

  • We will declare a python dictionary that will contain the vertices as their keys and distance from the source vertex as the associated values. 
  • Initially, we will assign the distance of each vertex from the source as infinite , denoted by a large number. Whenever we will find a vertex during traversal, we will calculate the current distance of the vertex from the source. If the current distance appears to be less than the distance mentioned in the dictionary containing the distance between source and other vertices, we will update the distance in the dictionary. 
  • After full breadth first traversal, we will have the dictionary containing the least distance from the source to each vertex. 

We can formulate the algorithm for calculating the shortest path length between vertices of an unweighted graph as follows.

  1. Create an empty Queue Q. 
  2. Create a list visited_vertices to keep track of visited vertices.
  3. Create a dictionary distance_dict to keep track of distance of vertices from the source vertex. Initialize the distances to 99999999. 
  4. Insert source vertex into Q and visited_vertices.
  5. If Q is empty, return. Else goto 6.
  6. Take out a vertex v from Q.
  7. Update the distances of unvisited neighbors of v in distance_dict. 
  8. Insert the unvisited neighbors to  Q and visited_vertices.
  9. Go to 5.
Implementation

As we have discussed the example and formulated an algorithm to find the shortest path length between source vertex and other vertices in a graph, let us implement the algorithm in python.

from queue import Queue graph = {'A': ['B', 'D', 'E', 'F'], 'D': ['A'], 'B': ['A', 'F', 'C'], 'F': ['B', 'A'], 'C': ['B'], 'E': ['A']} print("Given Graph is:") print(graph) def calculate_distance(input_graph, source): Q = Queue() distance_dict = {k: 999999999 for k in input_graph.keys()} visited_vertices = list() Q.put(source) visited_vertices.append(source) while not Q.empty(): vertex = Q.get() if vertex == source: distance_dict[vertex] = 0 for u in input_graph[vertex]: if u not in visited_vertices: # update the distance if distance_dict[u] > distance_dict[vertex] + 1: distance_dict[u] = distance_dict[vertex] + 1 Q.put(u) visited_vertices.append(u) return distance_dict distances = calculate_distance(graph, "A") for vertex in distances: print("Shortest Path Length to {} from {} is {}.".format(vertex, "A", distances[vertex]))

Output:

Given Graph is: {'A': ['B', 'D', 'E', 'F'], 'D': ['A'], 'B': ['A', 'F', 'C'], 'F': ['B', 'A'], 'C': ['B'], 'E': ['A']} Shortest Path Length to A from A is 0. Shortest Path Length to D from A is 1. Shortest Path Length to B from A is 1. Shortest Path Length to C from A is 2. Shortest Path Length to E from A is 1. Conclusion

In this article, we have discussed and implemented the algorithm to calculate the shortest path length between vertices in an unweighted graph. Here we have used the breadth first graph traversal algorithm. To read about binary tree traversal algorithms, you can read  Inorder tree traversal algorithm or level order tree traversal algorithm.

The post Shortest Path Length from a Vertex to other Vertices in a Graph appeared first on PythonForBeginners.com.

Categories: FLOSS Project Planets

PyCharm: Last day to buy PyCharm and Support Python!

Tue, 2021-11-30 09:01

You still have 1 day to purchase your PyCharm Pro license at 30% off and have the full amount of your purchase donated directly to the PSF!

Buy PyCharm and Support Python

PyCharm joins the Python Software Foundation on their end-of-the-year fundraiser one more time! Since November 9 you can purchase a new PyCharm Pro individual license at 30% off, and have the full amount of your purchase donated directly to the PSF.

The campaign ends tomorrow, December 1. If you still want to support Python, the time is now!

About the Partnership

The Python Software Foundation is the principal organization behind the Python programming language. As a non-profit organization, the PSF depends on sponsorships and donations to support its work. The contributions are used to maintain ongoing sprints, meetups, community events, Python documentation, fiscal sponsorships, software development, and community projects. None of this is possible without your support.

The end-of-the-year fundraiser is an important source of resources for the PSF and helps sustain programs that support the larger Python community. The Python Software Foundation and JetBrains have partnered before, conducting four consecutive Python Developers Surveys, and this year JetBrains PyCharm will once again support the Python Software Foundation in its fundraiser campaign.

Categories: FLOSS Project Planets

Real Python: Data Visualization Interfaces in Python With Dash

Tue, 2021-11-30 09:00

In the past, creating analytical web applications was a task for seasoned developers that required knowledge of multiple programming languages and frameworks. That’s no longer the case. Nowadays, you can make data visualization interfaces using pure Python. One popular tool for this is Dash.

Dash gives data scientists the ability to showcase their results in interactive web applications. You don’t need to be an expert in web development. In an afternoon, you can build and deploy a Dash app to share with others.

In this course, you’ll learn how to:

  • Create a Dash application
  • Use Dash core components and HTML components
  • Customize the style of your Dash application
  • Use callbacks to build interactive applications
  • Deploy your application on Heroku

[ 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 ]

Categories: FLOSS Project Planets

Talk Python to Me: #343: Do Excel things, get notebook Python code with Mito

Tue, 2021-11-30 03:00
Here's a question: What's the most common way to explore data? Would you say pandas and matplotlib? Maybe you went more general and said Jupyter notebooks. How about Excel, or Google Sheets, or Numbers, or some other spreadsheet app? Yeah, my bet is on Excel. And while it has many drawbacks, it makes exploring tabular data very accessible to many people, most of whom aren't even developers or data scientists. <br/> <br/> On this episode, we're talking about a tool called Mito. This is an add-in for Jupyter notebooks that injects an Excel-like interface into the notebook. You pass it data via a pandas dataframe (or some other source) and then you can explore it as if you're using Excel. The cool thing is though, just below that, it's writing the pandas code you'd need to do to actually accomplish that outcome in code. <br/> <br/> I think this will make pandas and Python data exploration way more accessible to many more people. So if you've been intimidated by pandas, or know someone who has, this could be what you've been looking for.<br/> <br/> <strong>Links from the show</strong><br/> <br/> <div><b>Mito</b>: <a href="https://www.trymito.io/" target="_blank" rel="noopener">trymito.io</a><br/> <b>Mito summary stats</b>: <a href="https://docs.trymito.io/how-to/summary-statistics" target="_blank" rel="noopener">trymito.io</a><br/> <b>pandas-profiling package</b>: <a href="https://github.com/pandas-profiling/pandas-profiling" target="_blank" rel="noopener">github.com</a><br/> <b>Lux API</b>: <a href="https://pypi.org/project/lux-api/" target="_blank" rel="noopener">pypi.org</a><br/> <b>Hex notebooks</b>: <a href="https://medium.com/short-bits/hex-a-new-collaborative-interactive-notebook-for-sql-and-python-154b8e4170e1" target="_blank" rel="noopener">medium.com</a><br/> <b>Deepnote</b>: <a href="https://deepnote.com/" target="_blank" rel="noopener">deepnote.com</a><br/> <b>Papermill</b>: <a href="https://papermill.readthedocs.io/en/latest/index.html" target="_blank" rel="noopener">papermill.readthedocs.io</a><br/> <b>JupterLite</b>: <a href="https://blog.jupyter.org/jupyterlite-jupyter-%EF%B8%8F-webassembly-%EF%B8%8F-python-f6e2e41ab3fa" target="_blank" rel="noopener">jupyter.org</a><br/> <b>Jupyter Desktop App</b>: <a href="https://github.com/jupyterlab/jupyterlab-desktop" target="_blank" rel="noopener">github.com</a><br/> <b>Jut</b>: <a href="https://github.com/kracekumar/jut" target="_blank" rel="noopener">github.com</a><br/> <b>Jupyter project</b>: <a href="https://jupyter.org/" target="_blank" rel="noopener">jupyter.org</a><br/> <b>Watch this episode on YouTube</b>: <a href="https://www.youtube.com/watch?v=XAGmSPZsYLU" target="_blank" rel="noopener">youtube.com</a><br/> <b>Episode transcripts</b>: <a href="https://talkpython.fm/episodes/transcript/343/do-excel-things-get-notebook-python-code-with-mito" target="_blank" rel="noopener">talkpython.fm</a><br/> <br/> <b>--- Stay in touch with us ---</b><br/> <b>Subscribe on YouTube</b>: <a href="https://talkpython.fm/youtube" target="_blank" rel="noopener">youtube.com</a><br/> <b>Follow Talk Python on Twitter</b>: <a href="https://twitter.com/talkpython" target="_blank" rel="noopener">@talkpython</a><br/> <b>Follow Michael on Twitter</b>: <a href="https://twitter.com/mkennedy" target="_blank" rel="noopener">@mkennedy</a><br/></div><br/> <strong>Sponsors</strong><br/> <a href='https://shortcut.com/talkpython'>Shortcut</a><br> <a href='https://talkpython.fm/linode'>Linode</a><br> <a href='https://talkpython.fm/assemblyai'>AssemblyAI</a><br> <a href='https://talkpython.fm/training'>Talk Python Training</a>
Categories: FLOSS Project Planets

Test and Code: 172: Designing Better Software with a Prototype Mindset

Tue, 2021-11-30 03:00

A prototype is a a preliminary model of something, from which other forms are developed or copied.
In software, we think of prototypes as early things, or a proof of concept.
We don't often think of prototyping during daily software development or maintenance. I think we should.
This episode is about growing better designed software with the help of a prototype mindset.

Sponsored By:

Support Test & Code in Python

Links:

<p>A prototype is a a preliminary model of something, from which other forms are developed or copied.<br> In software, we think of prototypes as early things, or a proof of concept.<br> We don&#39;t often think of prototyping during daily software development or maintenance. I think we should.<br> This episode is about growing better designed software with the help of a prototype mindset.</p><p>Sponsored By:</p><ul><li><a href="https://testandcode.com/pycharm" rel="nofollow">PyCharm Professional</a>: <a href="https://testandcode.com/pycharm" rel="nofollow">Try PyCharm Pro for 4 months and learn how PyCharm will save you time.</a> Promo Code: TESTANDCODE22</li></ul><p><a href="https://www.patreon.com/testpodcast" rel="payment">Support Test & Code in Python</a></p><p>Links:</p><ul><li><a href="https://snarky.ca/programming-language-selection-is-a-form-of-premature-optimization/" title="Selecting a programming language can be a form of premature optimization" rel="nofollow">Selecting a programming language can be a form of premature optimization</a> &mdash; Brett Cannon's blog post</li></ul>
Categories: FLOSS Project Planets

TestDriven.io: Reproducible Builds with Bazel

Mon, 2021-11-29 23:40
This article looks at how Bazel can be used to create reproducible, hermetic builds.
Categories: FLOSS Project Planets

Matthew Wright: Financial market data analysis with pandas

Mon, 2021-11-29 22:27

Pandas is a great tool for time series analysis of financial market data. Because pandas DataFrames and Series work well with a date/time based index, they can be used effectively to analyze historical data. By financial market data, I mean data like historical price information on a publicly traded financial instrument. However, any sort of … Continue reading Financial market data analysis with pandas

The post Financial market data analysis with pandas appeared first on wrighters.io.

Categories: FLOSS Project Planets

Pages