Planet Python
Last update: January 11, 2022 01:41 AM UTC
January 11, 2022
What is One-Hot Encoding in Data Science? and How to implement it in Python using Pandas or Scikit-Learn.
January 11, 2022 01:06 AM UTC
January 10, 2022
Solving Wordle Puzzles with Basic Python
Have you heard of Wordle? It’s a deceptively simple word puzzle. You’re asked to guess the word of the day, which is a five-letter word in English. If you guess wrong, you’re given a few hints: a letter in the word is green if your guess for that letter in that position is right; a yellow letter if that letter is present in the word, but not that position; and gray, if the letter is not in the word at all.
Deceptively simple, and yet quite challenging! Here’s how you can write a Wordle Solver with Python sets, list comprehensions, a bit of good luck!
Read More ->
January 10, 2022 03:38 PM UTC
In this four-part tutorial series, you’re building a social network with Django that you can showcase in your portfolio. This project is strengthening and demonstrating your understanding of relationships between Django models and showing you how to use forms so that users can interact with your app and with each other. You’re also making your site look good by using the CSS framework Bulma.
In the previous part of this tutorial series, you built templates and views for displaying a list of all profiles, as well as individual profile pages. You also learned how to apply style rules defined by the CSS framework Bulma to make your pages look good.
In the third part of this tutorial series, you’ll learn how to:
- Create the front-end interface to let users follow and unfollow profiles
- Submit and handle a POST request in Django using buttons
- Set up the model for your text-based content
- Build styled templates to display content on the front end
- Use intricate model relationships in template code
At the end of this part, your social network will have all the pages you’d expect, and you’ll be able to create dweets on the back end and display them on the front end. Your users will be able to discover and follow other users and read the contents of the profiles that they follow. They’ll also be able to click a button that sends an HTTP POST request handled by Django to unfollow a profile if they want to stop reading a certain user’s content.
You can download the code that you’ll need to start the third part of this project by clicking the link below and going to the source_code_start/ folder:
Demo
In this four-part tutorial series, you’re building a small social network that allows users to post short text-based messages. The users of your app can also follow other user profiles to see the posts of those users or unfollow them to stop seeing their text-based posts:
You’re also learning how to use the CSS framework Bulma to give your app a user-friendly appearance and make it a portfolio project you can be proud to show off!
In the third part of this tutorial series, you’ll continue working with Bulma-styled templates, and you’ll create the model for your text-based message content. You’ll also set up and handle HTTP POST request submissions on your Django app’s front end, which will allow users to follow or unfollow each other by clicking a button:
At the end of this tutorial, each user will be able to go to a new dashboard page to access a personal feed of dweets that’s based on which profiles they follow. They’ll also be able to follow and unfollow other users. That’s a giant leap ahead for your Django social network!
Project Overview
In this section, you’ll get an overview of what topics you’ll cover in this third part of the tutorial series. You’ll also get a chance to revisit the full project implementation steps, in case you need to skip back to a previous step from earlier in the series or if you want to see what’s still up ahead.
At this point, you should have finished working through parts one and two of this tutorial series. If you did, then you’re now ready to continue with the next steps of this tutorial series. These steps focus on the code logic for following and unfollowing profiles, as well as how to set up dweets:
After completing all the steps in the third part of the tutorial series, you can continue with part four.
To get a high-level idea of how you’re working through all four parts of this tutorial series on building your Django social network, you can expand the collapsible section below:
You’re implementing the project in a number of steps spread out over multiple separate tutorials in this series. There’s a lot to cover, and you’re going into detail along the way:
✅ Part 1: Models and Relationships
- Step 1: Set Up the Base Project
- Step 2: Extend the Django User Model
- Step 3: Implement a Post-Save Hook
✅ Part 2: Templates and Front-End Styling
- Step 4: Create a Base Template With Bulma
- Step 5: List All User Profiles
- Step 6: Access Individual Profile Pages
📍 Part 3: Follows and Dweets
- Step 7: Follow and Unfollow Other Profiles
- Step 8: Create the Back-End Logic For Dweets
- Step 9: Display Dweets on the Front End
⏭ Part 4: Forms and Submissions
- Step 10: Submit Dweets Through a Django Form
- Step 11: Prevent Double Submissions and Handle Errors
- Step 12: Improve the Front-End User Experience
Each of these steps will provide links to any necessary resources. By approaching the steps one at a time, you’ll have the opportunity to pause and come back at a later point in case you want to take a break.
With the high-level structure of this tutorial series in mind, you’ve got a good idea of where you’re at and which implementation steps you’ll handle in the last part.
Before getting started with the next step, take a quick look at the prerequisites to skim any links to other resources that might be helpful along the way.
Prerequisites
To successfully work through this part of your project, you need to have completed the first part on models and relationships and the second part on templates and styling, and you should confirm that your project is working as described there. It would be best if you’re also comfortable with the following concepts:
[ 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 ]
January 10, 2022 02:00 PM UTC
ItsMyCode |
The KeyError in Pandas occurs when you try to access the columns in pandas DataFrame, which does not exist, or you misspell them.
Typically, we import data from the excel name, which imports the column names, and there are high chances that you misspell the column names or include an unwanted space before or after the column name.
The column names are case-sensitive, and if you make a mistake, then Python will raise an exception KeyError: ‘column_name
Let us take a simple example to demonstrate KeyError in Pandas. In this example, we create a pandas DataFrame of employee’s data, and let’s say we need to print all the employee names.
# import pandas library
import pandas
import numpy as np
# create pandas DataFrame
df = pandas.DataFrame(np.array([["Jack", 22, "US"], ["Chandler", 55, "Canada"], ["Ross", 48, "India"]]),
columns=['name', 'age', 'country'])
# print names of employee
print(df["Name"])
Output
raise KeyError(key) from err
KeyError: 'Name'
When we run the program, Python raises KeyError, since we have misspelled the “name” column as “Name”.
Solution KeyError in Pandas
We can fix the issue by correcting the spelling of the key. If we are not sure what the column names are, we can print all the columns into the list as shown below.
# import pandas library
import pandas
import numpy as np
# create pandas DataFrame
df = pandas.DataFrame(np.array([["Jack", 22, "US"], ["Chandler", 55, "Canada"], ["Ross", 48, "India"]]),
columns=['name', 'age', 'country'])
# print names of employee
print(df["name"])
Output
0 Jack
1 Chandler
2 Ross
Name: name, dtype: object
We can now see a column called “name,” and we can fix our code by providing the correct spelling as a key to the pandas DataFrame, as shown below.
We can also avoid the KeyErrors raised by the compilers when an invalid key is passed. The DataFrame has a get method where we can give a column name and retrieve all the column values.
Syntax : DataFrame.get( 'column_name' , default = default_value_if_column_is_not_present)
If there are any misspelled or invalid columns, the default value will be printed instead of raising a KeyError. Let’s look at an example to demonstrate how this works.
# import pandas library
import pandas
import numpy as np
# create pandas DataFrame
df = pandas.DataFrame(np.array([["Jack", 22, "US"], ["Chandler", 55, "Canada"], ["Ross", 48, "India"]]),
columns=['name', 'age', 'country'])
# print names of employee
print(df.get("Name", default="Name is not present"))
‘Output
Name is not present
And if we provide the correct column name to the DataFrame.get() method, it will list all the column values present in that.
# import pandas library
import pandas
import numpy as np
# create pandas DataFrame
df = pandas.DataFrame(np.array([["Jack", 22, "US"], ["Chandler", 55, "Canada"], ["Ross", 48, "India"]]),
columns=['name', 'age', 'country'])
# print names of employee
print(df.get("name", default="Name is not present"))
Output
0 Jack
1 Chandler
2 Ross
Name: name, dtype: object
The post How to Fix: KeyError in Pandas? appeared first on ItsMyCode.
January 10, 2022 01:21 PM UTC
ItsMyCode |
In Python ValueError: Trailing data occurs when you try to load the JSON data or file into pandas DataFrame, and the data is written in lines separated with newline characters such as ‘\n’.
Typically, we import data from the JSON files, and there are higher chances that JSON data contains newline characters.
Let’s take a simple example to reproduce this error. We have a JSON file of employees, and the address property in the JSON has ‘\n’
JSON File
# import pandas library
import pandas as pd
# create pandas DataFrame
df = pd.read_json('employee.json')
# print names of employee
print(df)
Output
ValueError: Trailing data
Note: If the JSON data is malformed or the file path is invalid you will get an error ValueError: Expected object or value
Solution Python ValueError: Trailing data
The simplest way to fix this error is to pass the lines=True argument in the read_json() method while importing the JSON file.
The lines=True parameter ensures to read the JSON file as an object per line.
Now when we import the JSON file into a pandas DataFrame, it will load and print the data without any issue.
# import pandas library
import pandas as pd
# create pandas DataFrame
df = pd.read_json('employee.json',lines=True)
# print names of employee
print(df)
Output
ID name age address
0 123 Jack 25 #3, 5th Main \nIndia
1 124 Chandler 25 #5, 2nd Main \nUS
2 123 Jack 25 #3/2, 6th Main \nCanada
Another way is to remove the \n character from the address column. We can simply replace the \n character with an empty '' character, as shown below.
# import pandas library
import pandas as pd
# create pandas DataFrame
df = pd.read_json('employee.json',lines=True)
df['address'] = df['address'].str.replace('\n', ' ')
# print names of employee
print(df)
Output
ID name age address
0 123 Jack 25 #3, 5th Main India
1 124 Chandler 25 #5, 2nd Main US
2 123 Jack 25 #3/2, 6th Main Canada
The post How to Fix in Python ValueError: Trailing data? appeared first on ItsMyCode.
January 10, 2022 10:18 AM UTC
This week we welcome Lais Carvalho (@lais_bsc) as our PyDev of the Week! Lais is active in multiple Python user groups in Ireland and has helped organize multiple Python conferences. She is on a recent episode of Python Bytes too, so be sure to check that out!
If you'd like to see what projects Lais is working on, head on over to GitHub.

Let's spend a few moments getting to know Lais better!
Can you tell us a little about yourself (hobbies, education, etc.)
My name is Lais Carvalho and I work as Developer and Community Advocate for Quansight, a consultancy company that offers support for most of the Open Source libraries available, specially on the Python sphere. I have just graduated on IT (Information Technology), after studying engineering for two years. I also volunteer for Python Ireland and have helped organise a few Python conferences. My favourite ones are EuroPython (the biggest Python conference in Europe) and PyJamas, an online event where everyone is invited to present wearing pajamas.
Why did you start using Python?
I started using Python in my first year of engineering university. I was struggling to learn WolframAlpha to check if my handmade calculations were correct, but everything used to be so hard and take so long. That was when chatting to one of our teachers, he mentioned I might prefer to use Python for that. I thought “well, it doesn't cost me much to try” and have become a fan since then, which I believe was in 2014.
What other programming languages do you know and which is your favorite?
I am not a programmer, which means that my main line of work is with people (not code) but I can build small things using Java and Python. My R skills are not something to be proud of but I can make beautiful graphs and pretend I understand data analysis well enough. I would like to try and learn GoLang or Julia next.
My favourite do-it-all language is Python due to its versatility. But languages are tools, one is welcome to choose whichever (s)he knows best in order to get the job done. To expand on the metaphor, it is elementary that a plier will not be the most effective to hammer nails on a wall, but it might do a fine job on acceptable time if the amount of nails is small or the time is limited and hammers are not available.
What projects are you working on now?
I am currently on medical license due to a cancer diagnosis received two weeks before my thesis delivery deadline. I am now finished with the treatment (in theory) and waiting to hear results back from the hospital. Keeping fingers crossed.
Before that, I was working on updating the documentation of one of Quansight’s Open Source libraries named QHub.
Which Python libraries are your favorite (core or 3rd party)?
There are so many wonderful ones, which makes this a very challenging question but in summary, I quite like requests, making HTTP requests human-friendly since 2011. In addition, the more scientific ones like NumPy and SciPy, and the classy Manim for mathematical animations. Aw yes, and Flask for web apps! Not to mention the standard stuff, Python is all wonderful.
How did you become so active with Python user groups?

I started volunteering for PyCon Ireland in my second year in college (2019), because I believed networking was the most effective way to get into the industry. At the event, I met so many wonderful people and everyone had a project or initiative in need of help, so I volunteered. I remember being extremely excited about partaking in such an inclusive and fun community, so much so that when COVID restrictions arrived I became almost fully dedicated to the user groups. It was a good way to cope with lockdown and to meet wonderful people that ended up becoming close-personal friends of mine.
What advice do you have for people who would like to start their own local Python user groups?
Look around and see if there are people interested in joining you. Look for inspiration in existing groups and persevere. This is a huge community we are part of and there will always be someone willing to help in some way. Be vocal, ask for help, and don’t give up. Finally, if you are thinking about starting your own Python User Group in Ireland, come and speak to us at Python Ireland, we would be happy to help in any way we can.
Is there anything else you’d like to say?
I have just recorded an episode of Python Bytes that you can find on their website or on Spotify. Wanna ask me something? DM me on Twitter at @lais_bsc.
Python Ireland:
- A Speakers Coaching Session is happening later this month and if you want to improve your public speaking skills, it is a great opportunity to do so.
- Also, our monthly meetups happen on the second Wednesday of each month, online for now (due to COVID regulations) but working on coming back in person. The recorded sessions are added to the YouTube channel.
- For more information, follow us on Twitter. @pythonireland
PyLadies Dublin:
- All the PyLadies workgroups are incredible and they also need volunteers. If you’re looking for a safe place to join the Python Community, I would seriously recommend PyLadies! And the Dublin cohort is led by the wonderful Vicky.
EuroPython will start looking for volunteers for the in person event as well soon
Pyjamas happens in December, want to be notified about it? Follow us on twitter @PyjamasConf and subscribe to our YouTube channel.
Thanks for doing the interview, Lais!
The post PyDev of the Week: Lais Carvalho appeared first on Mouse Vs Python.
January 10, 2022 06:05 AM UTC
Zato is an integration platform and backend application server which means that, during most of their
projects, developers using Zato are interested in a few specific matters.
The platform concentrates on answering these key, everyday questions that Python backend developers routinely ask:
- How do I connect to external systems or databases to store or extract data?
- How do I map messages from one format to another?
- How do I automate my work so that it is repeatable across environments?
- How can I focus on my job instead of thinking of trivial low-level details?
- How do I debug my code?
- How can I reuse the skills and knowledge that I obtained elsewhere and how can I better myself?
- How do I manage the complexity of having to integrate at least several systems and dozens or hundreds of APIs?
The typical workflow
Dashboard
-
Dashboard is a web-based administration console that lets you define all the various connection pools,
security types, scheduler jobs or other integration assets that you later make use of in your Python-based API services
-
When you install Zato, it is comfortable to use its Dashboard to define resources like REST, MongoDB or SOAP connections pools
because it does not require any programming, you just fill out a form and that resource is created
Python
-
All of your code is in Python - that makes it easy to manipulate any kind of data that you receive or may need to access
-
In your code, you only deal with the business logic - if your service is invoked, it means that all the security
layers, serializers and other low-level parts have already completed their job and you are given a nice Python-based
business object that represents your input. Based on this input information, you create output that your business
logic dictates, still working purely on a high-level of Python objects, without any low-level details.
-
Static typing is encouraged through the use of dataclasses for your data models
-
Your code is hot-deployed from your IDE, no matter where your servers are, e.g. you work on Mac but the server
is a remote Linux instance
-
You can debug your services from your IDE as well and, again, the server can be a remote one
# -*- coding: utf-8 -*-
# stdlib
from dataclasses import dataclass
# Zato
from zato.server.service import Model, Service
@dataclass(init=False)
class GetClientRequest(Model):
client_id: int
@dataclass(init=False)
class GetClientResponse(Model):
name: str
email: str
segment: str
class GetClient(Service):
class SimpleIO:
input = GetClientRequest
output = GetClientResponse
def handle(self):
# Enable type checking and type completion
request = self.request.input # type: GetClientRequest
# Log details of our request
self.logger.info('Processing client `%s`', request.client_id)
# Produce our response - in a full service this information
# will be obtained from one or more databases or systems.
response = GetClientResponse()
response.name = 'Jane Doe'
response.email = 'hello@example.com'
response.segment = 'RNZ'
# Return the response to our caller
self.response.payload = response
Such a service can be assigned to one or more REST channels and we can invoke it now:
$ curl localhost:17010/api/v1/client -d '{"client_id":123}'
{"name":"Jane Doe","email":"hello@example.com","segment":"RNZ"}
$
Automation
-
Using Dashboard is very handy, and, once you are satisfied with what you created using it, the resources can be exported
from command line using a built-in tool called enmasse - the result is a regular YAML file that describes every
resource that you created using Dashboard
-
In the next step, an emasse file can be imported in a new environment, also from command line. For instance, you can
keep adding new connection definitions to the export file each day and they can be imported in a separate testing
environment by CI/CD regression testing processes.
-
Thanks to the enmasse export and import cycle, you do not need to manually recreate any resources that you initially
created in your development environment. Moreover, because enmasse files are simple YAML files, you can script their usage
in any way required when they are being import, e.g. by filling out credentials or other details that each environment
may differ by.
-
Similarly, with your Python code, you can commit your code to git and configure each environment to hot-deploy it directly
from a git checkout. Alternatively, Python code can be deployed statically, which requires a server restart. The latter
approach is useful when you, for instance, prepare an AWS AMI with your solution that you create new runtime instance from,
because it lets you embed your entire enmasse definition and code directly in your AMIs.
OpenAPI
-
Definitions of your services can be exported to OpenAPI
-
Note that, by default, your services can be multi-protocol - it means that you may have a service that only uses
WebSockets, or perhaps is a background one that has no REST endpoint at all, and yet, you still will be able to export it to
OpenAPI
-
Taken together, it means that you can use any OpenAPI-compatible tool, such as Postman, for accessing and testing
your API services, no matter if they use REST or not
-
You can also generate an entire static HTML site that will include OpenAPI as well as static pages describing your APIs -
this is useful, for instance when you need to share with your tech partners not only an OpenAPI definition but a pretty-looking
API documentation site as well
Let’s generate an OpenAPI definition for the GetClient service above:
$ zato openapi /path/to/server/server1 \
--include "client*" \
--file /tmp/openapi.yaml
Now, we can import the OpenAPI definition to Postman and invoke our services from it:
Python once more
-
Python is at the core of Zato and the platform allows you to leverage your already existing skills and knowledge
of third-party libraries
-
For instance, the code below is a stand-alone program that connects to Redis to insert a key and read it back:
# -*- coding: utf-8 -*-
# Redis
import redis
# Connect to the database
conn = redis.Redis(host='localhost', port=6379, db=0)
# Set a key ..
conn.set('key', 'value')
# .. read it back ..
result = conn.get('key')
# .. and log what we received.
print('Result', result)
- Now, the same as a Zato-based service:
# -*- coding: utf-8 -*-
# Zato
from zato.server.service import Service
class MyService(Service):
def handle(self):
# Set a key ..
self.kvdb.conn.set('key', 'value')
# .. read it back ..
result = self.kvdb.conn.get('key')
# .. and log what we received.
self.logger.info('Result %s', result)
-
In both cases, it is exactly the same amount of code yet a couple of differences are notable.
- First, because the configuration was created earlier using Dashboard or enmasse, your code
does not need to be concerned with where Redis is, it just makes use of it.
- Second, already at this point,
your Zato code is a scalable API service that can be hot-deployed to clusters for other systems to invoke it.
- Yet, the actual business logic, the usage of Redis, is the same, which means that you can reuse what you already
know and build upon it while developing with Zato.
-
Redis was but one example and the same principle applies to everything else. Be it SQL, MongoDB,
ElasticSearch or any other connection type, you can take your existing code and simply embed it in Zato services.
-
This also means that it is easy to find programming examples specific to a particular system because, in the end,
when you connect to such an external system through Zato, you issue requests using a library which already
is widely popular among Python programmers, like redis-py in this example above.
-
Similarly, as a data scientist you may already have some Pandas or Spark code developed earlier - the same principle
applies, you can embed it in your services or you can import it from your libraries, just like with regular Python code.
Next steps
-
Start the tutorial to learn how to integrate systems. After completing it, you will have a multi-protocol
service representing a sample scenario often seen in banking systems with several applications cooperating to provide a single and consistent API to its callers.
-
Visit the support page if you need assistance.
-
Para aprender más sobre las integraciones de Zato y API en español, haga clic aquí
-
Pour en savoir plus sur les intégrations API avec Zato en français, cliquez ici
January 10, 2022 04:40 AM UTC
I have a love/hate relationship with dependencies. I wrote about this
extensively on this blog. Once about the challenges with scaling trust
in dependencies and earlier about the
problem with micro dependencies.
Somehow very unsurprisingly nothing has actually improved in that regard
in the last 5 years. In fact, I think the problem has become
significantly worse. Where a few years back the main fear here was high
profile developers being targeted, the dependency discussion is now
overlapped and conflated with discussions about funding and
sustainability.
I'm sure everybody remembers the XKCD on dependencies:
What I like about this comic is that you can insert a whole bunch of
projects in your head into that comic. I like to imagine that the
mentioned project is Curl. It's maintained largely
by a single person — Daniel Stenberg — for more than 20 years. Curl is a
good example of an actual crucial dependency. It's everywhere. I have
seen it on game consoles, in cars, on MP3 players, smart speakers, bluray
players, embedded devices, command line utilities, backend servers, …
It's not only an incredible useful software, it's also solving a hard
problem. It's also not a small dependency either. Curl is a whole
package of useful functionality. If curl ceases to exist it would be
clearly bad for society.
However. How can curl disappear? Curl is not just one of the most
important dependencies, it's also one of the most resilient dependencies.
When you or me install curl, we rarely install it from the official
website. Curl is more likely to come from a mirror, vendored into a
library we're using, there are a lot of forks in proprietary code bases
etc. Curl is an unkillable dependency. Not only can the website go down,
also the original developer could probably go away and someone would pick
up the work, it's that useful.
Let's contrast this for a second with the situation on npm. One of the
most dependent on libraries is in fact colors. The library is effectively
emitting ANSI codes for colorization. A useful feature for sure, but not
world shattering. I would go out on a limb and say that this type of
functionality very often is implemented directly instead of depended on.
For instance when I wrote click I
purposefully decided to implement ANSI coloring right in my own library
without depending on something. My hunch is that it wouldn't take long to
rip out and replace
that library.
A few days ago the developer behind that library decided to release a new
version of the library that no longer does what it advertised on the tin.
Since it was a minor update quite a few people ended up with that version.
They didn't however even know that they were depending on “that one
package”, they probably pulled it in because something else in their
dependency chain needed it.
If you went to the GitHub repo of that developer you found two things:
some conspirational content in the readme of the repo, but also a
justification for why their library no longer did what it was supposed to
do: the developer was dissatisfied with “fortune 500” using their code for
free and asked for a six figure contract or for people to fork it.
What I wish people would actually start discussing when it comes to these
things is that npm (and other package managers) have developed into
incredible levers. Someone who has a package with a lot of dependents one
can easily knock out that piece of all modern digital infrastructure.
Daniel Stenberg of curl doesn't wield that power (and probably also
doesn't want to).
The risk a dependency poses is high with small, more commonly used
dependencies, by a single unvetted developer, installed through a package
manager like npm, cargo, pypi or similar. Yet when something goes wrong
there, everybody immediately notices and people quickly call for funding.
Yet those are not the dependencies that actually support our economy.
Many of those dependencies became that foundational, not because they are
solving a hard problem, but because we collectively started embracing
laziness over everything else. When we then focus our funding discussions
around these types of dependencies, we're implicitly also putting the
focus away from the actually important packages.
I appreciate what GitHub does with sponsors and I think it's an awesome
idea. I also appreciate that GitHub puts a finger at funding Open Source
being an issue, but unfortunately there is a dark side to this: it points
the finger to where it's easy. GitHub like npm point the finger to what
computers can easily explain. My code flew to mars. That's
awesome. But that Badge of honor I now carry on my GitHub profile I got
because they crawled the Python dependency list. Together with my badge
the folks that created lxml got a badge. However Daniel Veillard who
maintains the underling libxml2 library received no such badge. In fact
many people probably forget that libxml2 even exists or that they might be
using it, because it's hidden behind a much more fancy high level facade
that hides it. Unlike an npm package, you don't download libxml2 from
somewhere when you install lxml. libxml2 like curl doesn't have the
lever or visibility. Yet the amount of work and dedication that went into
the library is significant. And he's just one of thousands of developers
who have created incredible libraries we all still use.
Clearly we need to solve funding of Open Source projects and I love that
GitHub sponsors is a thing. But I think we need to find a better way to
assess impact of libraries than just how many people depend on this on
npm or other package managers. Because that's by far not the whole
picture.
January 10, 2022 12:00 AM UTC
January 09, 2022
ItsMyCode |
In Python, NameError: name ‘pd’ is not defined occurs when you import the pandas library but fail to provide the alias as pd while importing it.
In this article, let us look at what is NameError name pd is not defined and how to resolve this error with examples.
Solution NameError: name ‘pd’ is not defined
Let us take a simple example to reproduce this error. In the below example, we have imported the pandas library and created a pandas DataFrame.
# import pandas library
import pandas
import numpy as np
# create pandas DataFrame
df = pd.DataFrame(np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]),
columns=['a', 'b', 'c'])
# print dataframe
print(df)
Output
Traceback (most recent call last):
File "C:\Personal\IJS\Code\main.py", line 6, in <module>
df = pd.DataFrame(np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]),
NameError: name 'pd' is not defined. Did you mean: 'id'?
When we run the code, we get NameError: name ‘pd’ is not defined since we did not provide an alias while importing the pandas library.
There are multiple ways to resolve this issue. Let us look at all the approaches to solve the NameError.
Method 1 – Importing pandas with Alias as pd
The simplest way to resolve this error is by providing an alias as pd while importing the pandas library. Let’s fix our code by providing an alias and see what happens.
# import pandas library
import pandas as pd
import numpy as np
# create pandas DataFrame
df = pd.DataFrame(np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]),
columns=['a', 'b', 'c'])
# print dataframe
print(df)
Output
a b c
0 1 2 3
1 4 5 6
2 7 8 9
The syntax “import pandas as pd” is commonly used because it offers a more concise way to call pandas functions, and the code is more readable as we do not have to type “pandas” each time.
Method 2 – Importing all the functions from pandas
There might be a situation where you need to import all the functions from the pandas library, and to do that, we will be using the below syntax.
from pandas import *
In this case, you do not need any reference to call any functions of pandas. You can directly call the methods without using an alias, and in this example we can directly create the DataFrame as shown below.
# import pandas library
from pandas import *
import numpy as np
# create pandas DataFrame
df = DataFrame(np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]),
columns=['a', 'b', 'c'])
# print dataframe
print(df)
Output
a b c
0 1 2 3
1 4 5 6
2 7 8 9
Method 3 – Importing pandas package without an alias
Another way is to import a complete pandas package and call the functions directly with the pandas name without defining an alias.
# import pandas library
import pandas
import numpy as np
# create pandas DataFrame
df = pandas.DataFrame(np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]),
columns=['a', 'b', 'c'])
# print dataframe
print(df)
Output
a b c
0 1 2 3
1 4 5 6
2 7 8 9
In the above example, we import the complete pandas library and use pandas.DataFrame() method to create pandas DataFrame.
Note: If you are running the code in Jupyter notebook, ensure that you run the cell where you have imported the pandas and then run the rest of the code.
The post [Solved] NameError: name ‘pd’ is not defined appeared first on ItsMyCode.
January 09, 2022 08:26 PM UTC
ItsMyCode |
In Python, NameError: name ‘np’ is not defined occurs when you import the NumPy library but fail to provide the alias as np while importing it.
In this article, let us look at what is NameError name np is not defined and how to resolve this error with examples.
Solution NameError: name ‘np’ is not defined
Let us take a simple example to reproduce this error. In the below example, we have imported the NumPy library and defined a NumPy array.
# import numpy library
import numpy
# define numpy array
array = np.array([[12, 33], [21, 45]])
# print values in array format
print(array)
Output
Traceback (most recent call last):
File "C:\Personal\IJS\Code\main.py", line 5, in <module>
array = np.array([[12, 33], [21, 45]])
NameError: name 'np' is not defined
When we run the code, we get NameError: name ‘np’ is not defined since we did not provide an alias while importing the NumPy library.
There are multiple ways to resolve this issue. Let us look at all the approaches to solve the NameError.
Method 1 – Importing NumPy with Alias as np
The simplest way to resolve this error is by providing an alias as np while importing the NumPy library. Let’s fix our code by providing an alias and see what happens.
# import numpy library
import numpy as np
# define numpy array
array = np.array([[12, 33], [21, 45]])
# print values in array format
print(array)
Output
[[12 33]
[21 45]]
The syntax “import numpy as np” is commonly used because it offers a more concise way to call NumPy functions, and the code is more readable as we do not have to type “numpy” each time.
Method 2 – Importing all the functions from NumPy
There might be a situation where you need to import all the functions from the NumPy library, and to do that, we will be using the below syntax.
from numpy import *
In this case, you do not need any reference to call any functions of NumPy. You can directly call the methods without using an alias, as shown below.
# import numpy library
from numpy import *
# define numpy array
array = array([[12, 33], [21, 45]])
# print values in array format
print(array)
Output
[[12 33]
[21 45]]
Method 3 – Importing NumPy package without an alias
Another way is to import a complete NumPy package and call the functions directly with the NumPy name without defining an alias.
# import numpy library
import numpy
# define numpy array
array = numpy.array([[12, 33], [21, 45]])
# print values in array format
print(array)
Output
[[12 33]
[21 45]]
In the above example, we import the complete NumPy library and use numpy.array() method to create an array.
The post [Solved] NameError: name ‘np’ is not defined appeared first on ItsMyCode.
January 09, 2022 08:06 PM UTC
ItsMyCode |
If you pass all scalar values while creating pandas Dataframe in Python, you will encounter “ValueError: If using all scalar values, you must pass an index“
In this tutorial, we will learn what is ValueError: If using all scalar values, you must pass an index error means and how to resolve this ValueError in your program with examples.
Let us take a simple example to reproduce this issue.
# import pandas library
import pandas as pd
#define scalar values
a = 1
b = 2
c = 3
d = 4
# creating DataFrame from scalar values
df = pd.DataFrame({'A': a, 'B': b, 'C': c, 'D': d})
print(df)
Output
raise ValueError("If using all scalar values, you must pass an index")
ValueError: If using all scalar values, you must pass an index
In the above example, we have declared scalar value and attempted to create a pandas DataFrame by passing a scalar value.
When we run the code, Python will raise ValueError: If using all scalar values, you must pass an index
How to fix ValueError: If using all scalar values, you must pass an index?
The most common way to create DataFrames in Python is by using lists and dictionaries. There are three ways to fix the error. Let us look at each of them with examples.
The simplest way is to transform the scalar values into a list and pass it to a DataFrame, as shown below.
# import pandas library
import pandas as pd
#define scalar values
a = 1
b = 2
c = 3
d = 4
# creating DataFrame by transforming Scalar Values to List
df = pd.DataFrame({'A': [a], 'B': [b], 'C': [c], 'D': [d]})
print(df)
Output
A B C D
0 1 2 3 4
Method 2: Place Scalar Values into Dictionary
Another way is to place the scalar values into the dictionary and pass it to Pandas DataFrame as shown below.
# import pandas library
import pandas as pd
#define scalar values
a = 1
b = 2
c = 3
d = 4
# storing the dictionary of scalar values
p_dict = {'A':1, 'B':2, 'C':3, 'D':4}
# creating DataFrame by passing dictionary into List
df = pd.DataFrame(p_dict)
print(df)
Output
A B C D
0 1 2 3 4
Method 3: Pass Scalar Values and Pass Index
We can even pass an index with scalar values to DataFrame. When you pass an index, pandas will treat your dictionary keys as column names and the values as what the column should contain for each of the values in the index.
# import pandas library
import pandas as pd
# define scalar values
a = 1
b = 2
c = 3
d = 4
# creating DataFrame from scalar values and passing index
df = pd.DataFrame({'A': a, 'B': b, 'C': c, 'D': d}, index=[0])
print(df)
Output
A B C D
0 1 2 3 4
The post ValueError: If using all scalar values, you must pass an index appeared first on ItsMyCode.
January 09, 2022 05:58 PM UTC
ItsMyCode |
In Python matplotlib No handles with labels found to put in legend occur if you have not defined the label parameters whenever you plot the figure and try to call the plt.legend() method.
The matplotlib.pyplot is a state-based interface to matplotlib and provides a way to plot interactive figures in Python.
We can use matplotlib.pyplot.legend() method to place a legend on the axes.
However, if we do not add the labels parameter and then call the matplotlib.pyplot.legend() function, you will get No handles with labels found to put in legend.
If you are using the latest version of Python, then the error would be No artists with labels found to put in legend. Note that artists whose label start with an underscore are ignored when legend() is called with no argument.
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 20, 2000)
y1 = np.sin(x)
y2 = np.arcsin(x)
plt.plot(x, y1)
plt.plot(x, y2)
plt.legend()
plt.show()
Output
No handles with labels found to put in legend.Note that artists whose label start with an underscore are ignored when legend() is called with no argument.
Another way you get this error is if you call the legend method before plotting it. Ensure to verify your code and call the legend function after completing the plotting.
Solution – No handles with labels found to put in legend
Now that we know why the error occurs, let us see how to resolve the error and plot the legends correctly.
There are three different ways to call the matplotlib.pyplot.legend() method in Python.
Calling legend() without any arguments
If you want the legends to be detected automatically, you can call legend() method without passing any arguments. This will automatically detect the legend elements, including the labels, and plot them for you.
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 8, 1000)
y1 = np.sin(x)
y2 = np.arcsin(x)
plt.plot(x, y1, label='sin')
plt.plot(x, y2, label='arcsin')
plt.legend()
plt.show()
Output
Passing labels as arguments to legend() method
You can pass the labels as an argument to the legend() method as iterable of strings.
Each string is used as a label for the elements in the order they were created.
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 8, 1000)
y1 = np.sin(x)
plt.plot([4, 7, 9])
plt.plot(x, y1, '-b')
plt.legend(['Line1', 'Line2'])
plt.show()
Note: This is not the recommended approach since the relationship between the elements and the passed labels exist only through the order it created and can lead to confusion.
Passing handles and labels as a parameter to legend() method
If we need complete control, we can pass the elements followed by the iterable of strings as labels explicitly to the legend() function.
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 8, 1000)
y1 = [4, 7, 9]
y2 = np.sin(x)
y3 = np.arcsin(x)
line, = plt.plot(y1)
sine, = plt.plot(x, y2)
arcsine, = plt.plot(x, y3)
plt.legend(handles = [line, sine, arcsine],
labels = ['Line', 'Sine', 'Arcsine'])
plt.show()
Reference: Stackoverflow, Educative
The post No handles with labels found to put in legend appeared first on ItsMyCode.
January 09, 2022 04:22 PM UTC
This release adds support for scikit-learn 1.0, which includes support for feature names. If you pass a pandas dataframe to fit, the estimator will set a feature_names_in_ attribute containing the feature names. When a dataframe is passed to predict, it is checked that the column names are consistent with those passed to fit.
The
example below
illustrates this feature.
For a full list of changes in scikit-survival 0.17.0, please see the
release notes.
Installation
Pre-built conda packages are available for Linux, macOS, and Windows via
conda install -c sebp scikit-survival
Alternatively, scikit-survival can be installed from source following
these instructions.
Feature Names Support
Prior to scikit-survival 0.17, you could pass a pandas dataframe to estimators’ fit
and predict methods, but the estimator was oblivious to the
feature names accessible via the dataframe’s columns attribute.
With scikit-survival 0.17, and thanks to scikit-learn 1.0,
feature names will be considered when a dataframe is passed.
Let’s illustrate feature names support using the Veteran’s Lung Cancer dataset.
from sksurv.datasets import load_veterans_lung_cancer
X, y = load_veterans_lung_cancer()
X.head(3)
|
Age_in_years |
Celltype |
Karnofsky_score |
Months_from_Diagnosis |
Prior_therapy |
Treatment |
| 0 |
69.0 |
squamous |
60.0 |
7.0 |
no |
standard |
| 1 |
64.0 |
squamous |
70.0 |
5.0 |
yes |
standard |
| 2 |
38.0 |
squamous |
60.0 |
3.0 |
no |
standard |
The original data has 6 features, three of which contain strings, which
we encode as numeric using OneHotEncoder.
from sksurv.preprocessing import OneHotEncoder
transform = OneHotEncoder()
Xt = transform.fit_transform(X)
Transforms now have a get_feature_names_out() method, which will
return the name of features after the transformation.
transform.get_feature_names_out()
array(['Age_in_years', 'Celltype=large', 'Celltype=smallcell',
'Celltype=squamous', 'Karnofsky_score', 'Months_from_Diagnosis',
'Prior_therapy=yes', 'Treatment=test'], dtype=object)
The transformed data returned by OneHotEncoder is again a dataframe,
which can be used to fit
Cox’s proportional hazards model.
from sksurv.linear_model import CoxPHSurvivalAnalysis
model = CoxPHSurvivalAnalysis().fit(Xt, y)
Since we passed a dataframe, the feature_names_in_ attribute will contain
the names of the dataframe used when calling fit.
model.feature_names_in_
array(['Age_in_years', 'Celltype=large', 'Celltype=smallcell',
'Celltype=squamous', 'Karnofsky_score', 'Months_from_Diagnosis',
'Prior_therapy=yes', 'Treatment=test'], dtype=object)
This is used during prediction to check that the data matches the format
of the training data. For instance, when passing a raw numpy array instead
of a dataframe, a warning will be issued.
pred = model.predict(Xt.values)
UserWarning: X does not have valid feature names, but CoxPHSurvivalAnalysis was fitted with feature names
Moreover, it will also check that the order of columns matches.
X_reordered = pd.concat(
(Xt.drop("Age_in_years", axis=1), Xt.loc[:, "Age_in_years"]),
axis=1
)
pred = model.predict(X_reordered)
FutureWarning: The feature names should match those that were passed during fit. Starting version 1.2, an error will be raised.
Feature names must be in the same order as they were in fit.
For more details on feature names support, have a look at the
scikit-learn release highlights.
January 09, 2022 03:45 PM UTC
ItsMyCode |
The TypeError: can’t multiply sequence by non-int of type ‘str’ occurs if we multiply a string by another string without converting into an integer or floating-point.
In this tutorial, we will learn what exactly TypeError: can’t multiply sequence by non-int of type ‘str’ error means and how to resolve this TypeError in your program with examples.
TypeError: can’t multiply sequence by non-int of type ‘str’
Python is one of the best programming languages because of its features and simplicity. One such fantastic feature in Python is we can multiply strings with numbers.
Multiplying string with an integer
Let’s take an example to demonstrate multiplying string with numbers.
The other popular programming languages will never let you to multiple strings and integers. However, we can perform a multiplication between string and integer in Python. After the multiplication, the string is repeated for n times, as shown below.
text = "ItsMyCode"
n = 3
print(text*n)
Output
ItsMyCodeItsMyCodeItsMyCode
Here the string “ItsMyCode” is repeated multiplied by three and repeated three times in the output.
If we try to multiply the string with another string then the Python interpreter will throw TypeError: can’t multiply sequence by non-int of type ‘str’.
Multiplying string with another string
You cannot multiply a string with a non-integer value in Python. If we multiply a string with another string without converting to integer or floating point, we get an error can’t multiply sequence by non-int of type ‘str’.
Let us take a simple example of multiplying two numbers.
num1 ='5'
num2 ='6'
output =num1 * num2
print(output)
Output
Traceback (most recent call last):
File "C:\Personal\IJS\Code\main.py", line 3, in <module>
output =num1 * num2
TypeError: can't multiply sequence by non-int of type 'str'
Even though the number entered here is equal to the integer values, the Python interpreter will still consider it as a string and raise a TypeError.
The simplest way to resolve this issue is by converting both the strings into an integer and then performing a multiplication operation, as shown below.
num1 ='5'
num2 ='6'
output = int(num1) * int(num2)
print(output)
Output
30
Solution TypeError: can’t multiply sequence by non-int of type ‘str’
Now we know that TypeError: can’t multiply sequence by non-int of type str is caused by multiplying a string with another string. Let us see how we can resolve this error with an example.
Usually, we get this error when we receive input from the user, and the input() method alway returns the data in a string format.
Consider we have to calculate the total tax amount paid based on the distance traveled and the fare price.
In the above example, we are reading the fare price and distance data as user input, and we are calculating the tax amount by multiplying the (fare_price * distance)*(tax_percentage/100)
Even though the user inputs valid data, the input() method returns a string, meaning that fare_price and distance values are in string format. Hence we end up multiplying two strings resulting in the TypeError: can’t multiply sequence by non-int of type ‘str’.
tax_percentage = 5
fare_price = input("Please enter the fare amount charged ")
distance = input("Please enter the distance travelled to calculate the total fare - ")
total_fare = (fare_price * distance) * (5/100)
print(total_fare)
Output
Please enter the fare amount charged 100
Please enter the distance travelled to calculate the total fare - 5
Traceback (most recent call last):
File "C:\Personal\IJS\Code\main.py", line 4, in <module>
total_fare = (fare_price * distance) * 0.05
TypeError: can't multiply sequence by non-int of type 'str'
The best way to resolve this error is to convert the user input string to a floating-point using the float() method.
This allows us to multiply the order_value and discount because both are floating-point numbers.
tax_percentage = 5
fare_price = float(input("Please enter the fare amount charged "))
distance = float(input("Please enter the distance travelled to calculate the total fare - "))
total_fare = (fare_price * distance) * (5/100)
print(total_fare)
Output
Please enter the fare amount charged 250.50
Please enter the distance travelled to calculate the total fare - 3.4
42.585
Note: We cannot multiply strings with floating-point numbers,if we do Python interpreter will throw TypeError: can't multiply sequence by non-int of type 'float'. Hence in the above example we have to convert both the inputs into floating-point and then perform multiplication.
Conclusion
We cannot multiply strings with any non integers values such as float, string etc. If we multiply a string with another string without converting into an integer we get TypeError: can’t multiply sequence by non-int of type 'str'
In order to solve this issue, TypeError: can’t multiply sequence by non-int of type ‘str’ ensure that either you are performing a multiplication between string and integer or alternatively you can convert all the string values into a floating-point number before performing any calculations.
The post [Solved] Python can’t Multiply Sequence by non-int of type ‘str’ appeared first on ItsMyCode.
January 09, 2022 11:35 AM UTC
Swift 5.5 brought us async functions. ArgumentParser is the most popular way
to write command line interfaces with Swift. Swift 5.5 supports an asynchronous main
function, but ArgumentParser does not, as of version 1.0.2.
To bridge this gap, you can call ArgumentParser manually from your asynchronous main
function, like this:
import ArgumentParser
struct MyCommand: ParsableCommand {
@Argument var arg: String
// Usually you'd write a `run` function, but it has to be synchronous.
func runAsync() async throws {
/* … */
}
}
@main
enum Main {
static func main() async throws {
let args = Array(CommandLine.arguments.dropFirst())
do {
let command = try MyCommand.parse(args)
try await command.runAsync()
} catch {
MyCommand.exit(withError: error)
}
}
}
January 09, 2022 10:00 AM UTC
ItsMyCode |
If you are accessing the elements of a list in Python, you need to access it using its index position or slices. However, if you try to access a list value using a string Python will raise TypeError: list indices must be integers or slices, not str exception.
In this tutorial, we will learn what “list indices must be integers or slices, not str” error means and how to resolve this TypeError in your program with examples.
TypeError: list indices must be integers or slices, not str
Lists are always indexed using a valid index number, or we can use slicing to get the elements of the list. Below is an example of indexing a list.
# Example 1: of list indexing
my_list = [1, 2, 3, 4, 5, 6, 7, 8]
print(my_list[5])
# Example 2: of list slicing
fruits = ["Apple", "Orange", "Lemon", "Grapes"]
print("Last 2 fruits is", fruits[2:4])
Output
6
Last 2 fruits is ['Lemon', 'Grapes']
The first example is we use an integer as an index to get the specific element of a list.
In the second example, we use a Python slicing technique by defining a start point and end-point to retrieve the sublist from the main list.
Now that we know how to access the elements of the list, there are several scenarios where developers tend to make mistakes, and we get a TypeError. Let us take a look at each scenario with examples.
It’s the most common scenario where we do not convert the input data into a valid type in Menu-driven programs, leading to TypeError. Let us take an example to reproduce this issue.
Consider an ATM menu-driven example where the user wants to perform certain operations by providing the input to the program.
menu = ["Deposit Cash", "Withdraw Case", "Check Balance", "Exit"]
choice = input(
'Choose what would you like to perform (Valid inputs 0, 1, 2, 3)')
print(menu[choice])
Output
Choose what would you like to perform (Valid inputs 0, 1, 2, 3)2
Traceback (most recent call last):
File "C:\Personal\IJS\Code\main.py", line 13, in <module>
print(menu[choice])
TypeError: list indices must be integers or slices, not str
When the user inputs any number from 0 to 3, we get TypeError: list indices must be integers or slices, not str, because we are not converting the input variable “choice” into an integer, and the list is indexed using a string.
We can resolve the TypeError by converting the user input to an integer, and we can do this by wrapping the int() method to the input, as shown below.
menu = ["Deposit Cash", "Withdraw Case", "Check Balance", "Exit"]
choice = int(input(
'Choose what would you like to perform (Valid inputs 0, 1, 2, 3) - ' ))
print(menu[choice])
Output
Choose what would you like to perform (Valid inputs 0, 1, 2, 3) - 2
Check Balance
Scenario 2: Trying to access Dictionaries list elements using a string
Another reason we get TypeError while accessing the list elements is if we treat the lists as dictionaries.
In the below example, we have a list of dictionaries, and each list contains the actor and name of a movie.
actors = [
{
'name': "Will Smith",
'movie': "Pursuit of Happiness"
},
{
'name': "Brad Pitt",
'movie': "Ocean's 11"
},
{
'name': "Tom Hanks",
'movie': "Terminal"
},
{
'name': "Leonardo DiCaprio",
'movie': "Titanic"
},
{
'name': "Robert Downey Jr",
'movie': "Iron Man"
},
]
actor_name = input('Enter the actor name to find a movie - ')
for i in range(len(actors)):
if actor_name.lower() in actors['name'].lower():
print('Actor Name: ', actors['name'])
print('Movie: ', actors['movie'])
break
else:
print('Please choose a valid actor')
Output
Enter the actor name to find a movie - Brad Pitt
Traceback (most recent call last):
File "C:\Personal\IJS\Code\program.py", line 27, in <module>
if actor_name.lower() in actors['name'].lower():
TypeError: list indices must be integers or slices, not str
We need to display the movie name when the user inputs the actor name.
When we run the program, we get TypeError: list indices must be integers or slices, not str because we are directly accessing the dictionary items using the key, but the dictionary is present inside a list.
If we have to access the particular value from the dictionary, it can be done using the following syntax.
list_name[index_of_dictionary]['key_within_dictionary']
We can resolve this issue by properly iterating the dictionaries inside the list using range() and len() methods and accessing the dictionary value using a proper index and key, as shown below.
actors = [
{
'name': "Will Smith",
'movie': "Pursuit of Happiness"
},
{
'name': "Brad Pitt",
'movie': "Ocean's 11"
},
{
'name': "Tom Hanks",
'movie': "Terminal"
},
{
'name': "Leonardo DiCaprio",
'movie': "Titanic"
},
{
'name': "Robert Downey Jr",
'movie': "Iron Man"
},
]
actor_name = input('Enter the actor name to find a movie - ')
for i in range(len(actors)):
if actor_name.lower() in actors[i]['name'].lower():
print('Actor Name: ', actors[i]['name'])
print('Movie: ', actors[i]['movie'])
break
else:
print('Please choose a valid actor')
Output
Enter the actor name to find a movie - Brad Pitt
Actor Name: Brad Pitt
Movie: Ocean's 11
Conclusion
The TypeError: list indices must be integers or slices, not str occurs when we try to index the list elements using string. The list elements can be accessed using the index number (valid integer), and if it is a dictionary inside a list, we can access using the syntax list_name[index_of_dictionary]['key_within_dictionary']
The post TypeError: list indices must be integers or slices, not str appeared first on ItsMyCode.
January 09, 2022 07:35 AM UTC
January 08, 2022
As part of my series on Python&aposs syntax, I want to tackle the from clause for raise statements. In case you&aposre unfamiliar, raise A from B causes B to be assigned to A.__cause__ which lets chained tracebacks exist (as well as __context__, but that&aposs not relevant to today&aposs topic). There is a restriction that only instances of exceptions can be assigned to __cause__, and if you specify an exception class then it gets instantiated before assignment. Trying to assign anything else triggers a TypeError.
So the first question is how much checking do we need to do for the from clause&aposs object to make sure it meets the requirement of being an (eventual) exception instance?
>>> exc1 = Exception()
>>> exc1.__cause__ = 42
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: exception cause must be None or derive from BaseException
>>> exc1.__cause__ = Exception
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: exception cause must be None or derive from BaseException
>>> exc1.__cause__ = Exception()
>>>
Exploring restrictions when assigning to
BaseException.__cause__It appears that only assigning an instance of an exception to __cause__ is allowed. This is convenient as we don&apost have to do the check for something not being an exception instance. But it&aposs also inconvenient as we do have to instantiate any exception class ourselves. What this says to me is the following:
- Assigning an exception instance is fine.
- Assigning a non-exception-related object is "fine" because the exception object will raise the exception.
- Assigning an exception class is problematic, and so we will have to handle the instantiation.
So how do we detect if an object is an exception class but not an instance? To tell if an object is a class, it needs to be an instance of type (as inspect.issclass() shows us); isinstance(obj, type). To tell if something is an exception instance, it needs to be an instance of BaseException; isinstance(obj, BaseException). And to tell if a class is an exception class, we need to know if it subclasses BaseException; issubclass(obj, BaseException). Now one thing to note is issubclass() will raise a TypeError if you pass anything that isn&apost a class as its first argument; isinstance() does not have the inverse issue of passing in a class as its first argument.
Oh, and we also have to make sure the object we are raising is also appropriately instantiated before we attempt any assignment to __cause__. That adds an extra wrinkle to this problem as it means we will have to raise the TypeError when the to-be-raised exception isn&apost an exception-related object.
This can all be summarized by the following function:
def exception_instance(obj):
if isinstance(obj, BaseException):
return obj
elif isinstance(obj, type) and issubclass(obj, BaseException):
return obj()
else:
raise TypeError("exceptions must derive from BaseException")
Utility function for getting an exception instance
When we unravel raise A from B, we can inline the logic and simplify it a bit:
- If we have an exception class, instantiate it.
- If we have a non-exception object for the
raise clause, raise TypeError. - Rely on the fact that assigning anything other than an exception instance to
__cause__ raises the appropriate TypeError for us. - Don&apost assign anything if the
from clause evaluates to None.
This lets us unravel raise A from B to:
_raise = A
if isinstance(_raise, type) and issubclass(_raise, BaseException):
_raise = _raise()
elif not isinstance(_raise, BaseException):
raise TypeError("exceptions must derive from BaseException")
_from = B
if isinstance(_from, type) and issubclass(_from, BaseException):
_from = _from()
if _from is not None:
_raise.__cause__ = _from
raise _raise
Unravelling
raise A from BIn the general case of raise A we don&apost have to do any of this as it&aposs part of Python&aposs semantics to handle the class-to-instance scenario.
January 08, 2022 11:07 PM UTC
ItsMyCode |
Python string swapcase() method is a built-in function that converts all uppercase characters into lowercase and all lowercase characters into uppercase characters of a given string and returns a new string.
swapcase() Syntax
The Syntax of swapcase() method is:
string.swapcase()
swapcase() Parameters
The swapcase() method doesn’t take any parameters.
swapcase() Return Value
The swapcase() method returns a copy of the string where all the uppercase characters are converted into lowercase characters and vice-versa.
In case the string has other than alphabets those characters will not be converted and returned as-is.
Example: Python Program to change the case of a given string
text1 = "pYTHON tUTORIALS"
print(text1.swapcase())
text2 = "HELLO WORLD"
print(text2.swapcase())
text3 = "welcome to itsmycode"
print(text3.swapcase())
text4 ="12345!!!"
print(text4.swapcase())
Output
Python Tutorials
hello world
WELCOME TO ITSMYCODE
12345!!!
Note: If you want to convert given string into lowercase only it is recommended to use lower() method. Likewise, if you want to convert given string into uppercase only it is recommended to use upper() method.
The post Python String swapcase() appeared first on ItsMyCode.
January 08, 2022 11:50 AM UTC
The team at Instagram dropped a performance bomb on the Python world when they open-sourced Cider, their performance oriented fork of CPython. It contains a number of performance optimizations, including bytecode inline caching, eager evaluation of coroutines, a method-at-a-time JIT, and an experimental bytecode compiler that uses type annotations to emit type-specialized bytecode that performs better in the JIT.
<br/>
<br/>
While it's not a general purpose runtime we can all pick up and use, it contains many powerful features and optimizations that may make their way back to mainline Python.
<br/>
<br/>
We welcome Dino Viehland to dive into Cinder.<br/>
<br/>
<strong>Links from the show</strong><br/>
<br/>
<div><b>Dino on Twitter</b>: <a href="https://twitter.com/DinoViehland" target="_blank" rel="noopener">@DinoViehland</a><br/>
<b>Cinder Python Runtime</b>: <a href="https://github.com/facebookincubator/cinder" target="_blank" rel="noopener">github.com/facebookincubator</a><br/>
<b>Dino's PyCon talk</b>: <a href="https://www.youtube.com/watch?v=xGY45EmhwrE" target="_blank" rel="noopener">youtube.com</a><br/>
<b>IronPython</b>: <a href="https://ironpython.net/" target="_blank" rel="noopener">ironpython.net</a><br/>
<b>Sam Gross's NoGil work</b>: <a href="https://github.com/colesbury/nogil" target="_blank" rel="noopener">github.com/colesbury/nogil</a><br/>
<b>Pyjion</b>: <a href="https://www.trypyjion.com/" target="_blank" rel="noopener">trypyjion.com</a><br/>
<b>uWSGI</b>: <a href="https://uwsgi-docs.readthedocs.io/en/latest/" target="_blank" rel="noopener">uwsgi-docs.readthedocs.io</a><br/>
<b>Configuring uWSGI at Bloomberg</b>: <a href="https://www.techatbloomberg.com/blog/configuring-uwsgi-production-deployment/" target="_blank" rel="noopener">techatbloomberg.com</a><br/>
<b>Locust perf testing</b>: <a href="https://locust.io/" target="_blank" rel="noopener">locust.io</a><br/>
<b>Watch this episode on YouTube</b>: <a href="https://www.youtube.com/watch?v=XHVaEj9fnA8" target="_blank" rel="noopener">youtube.com</a><br/>
<b>Episode transcripts</b>: <a href="https://talkpython.fm/episodes/transcript/347/cinder-specialized-python-that-flies" 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://talkpython.fm/sentry'>Sentry Error Monitoring, Code TALKPYTHON</a><br>
<a href='https://talkpython.fm/toptal'>TopTal</a><br>
<a href='https://talkpython.fm/assemblyai'>AssemblyAI</a><br>
<a href='https://talkpython.fm/training'>Talk Python Training</a>
January 08, 2022 08:00 AM UTC
January 07, 2022
This blog post is a repost of the original technical overview of the Trading Strategy protocol software stack for community feed aggregators. Please read the original blog post for the best layout and formatting.
The audience of this post is software developers who are looking to build scalable software-as-a-service solutions and are interested in Svelte, Python and TimescaleDB technologies. Developers who are interested in Web3, Ethereum, cryptocurrency and blockchain technologies will also find this post useful.
What are Trading Strategy protocol and algorithmic trading?
Trading Strategy is a new service for algorithmic and technical trading of cryptocurrencies on decentralised exchange (DEXes).
Algorithmic trading is a derivative of technical analysis; taking trading positions based on pure mathematics and data. Algorithmic trading is part of quantitative finance, the opposite of value investing where trading decisions are made based on fundamentals. Algorithmic trading provides a systematic approach to trading compared to methods based on trader intuition or instinct. Whereas technical analysis often aids humans to take trading positions, in its purest form in algorithmic trading a trading program follows a set of trading rules and independently executes trades on the market 24/7.
Today, Trading Strategy offers market data feeds for Uniswap compatible exchanges across three different blockchains (Ethereum, Binance Smart Chain, Polygon). We expect to cover all major decentralised exchanges and exchange types on all major blockchains by the end of the year.
Our mission is to make algorithmic by developing and investing in algorithmic trading strategies easy. Although serving the market data is the first step, Trading Strategy is going to grow beyond the information service website. During the course of 2022, the service will be decentralised, so that the whole software solution, strategy and trade execution will be runnable anyone independently (so-called operating a node).
You can read more about our future plans in our vision blog post.
Rich in technical wealth
Trading Strategy chose modern architecture and the best components of 2021 for its software development, making its codebase high in technical wealth.
Technical wealth is the opposite of technical debt. As Trading Strategy was able to start as a clean slate project, we had the privilege to pick the latest technologies and build our architecture around these. This enables us to build faster and do changes more dynamically. As an example, a lot of out of the box features offered by TimescaleDB would have taken us months if we had built them ourselves.
The decentralised finance (DeFi) industry itself is high in technical wealth compared to traditional finance (TradFi). This is due to the use of public ledger (open data), free-as-in-speech codebases (open source) and permissionless public blockchains (open access). This is the opposite of the traditional financial services that are built around closed networks, private APIs and exclusive access. Privileged and siloed software development leads to high maintenance cost long term, as there are no people who are able to work with the code. For references, see this blog post on legacy investment bank software and Google’s woes about maintaining their own Linux kernel with 9000+ in-house patches. Writing financial applications for DeFi is 10x – 100x more developer productive than writing them for TradFi.
What is a Web3?
From the software developer point of view, Web3 refers to backend-free services. No logins or registrations are needed. The user data is not processed and stored on a private server, but a public blockchain where the business logic is wired together using smart contracts. Any transaction, or a “POST request” in the traditional parlay, is initiated by users themselves, using their private key on their locally stored wallet application.
In this kind of model, there are no sysadmin fraud risks, no data loss risks or data liability risks with user identity information. The user is in 100% control. It is a fairer world where users have more control over the revenue streams they generate. Big IT like Facebook and Google have fewer unfair monetization opportunities on user data.
Only some services are a good fit for Web3. At the moment Web3 works best for pseudonymous and public data use cases. This is almost all finance, provenance (NFTs), public social media like Twitter and discussion forums and eCommerce.
Web3 is still early: though most pieces have been figured out in computer science theory, the implementation is still under development. For example, doing database-like traffic (ThreadDB) and storage (Arweave, Storj) can be still considered “alpha” today.
Software stack overview
Below is a walkthrough of how the HTTP requesting of Trading Strategy website is set up. Because Trading Strategy application is eventually going to be a Web3-like oracle node in a distributed network, everything built API first. There are no internal APIs – the website uses the same public market data APIs as everyone else.
Trading Strategy Oracle is a process that indexes blockchain data: DEX trading data, tokens and so on. Oracle and web processes communicate over TimescaleDB. Oracle is responsible for tasks like generating OHLCV candle data, generating liquidity maps and fetching US dollar reference prices. Oracle processes connect to various blockchain GoEthereum nodes that are part of the P2P network for the respective Ethereum Virtual Machine based blockchains.
Frontend: Why did we choose Svelte?
Svelte is a new JavaScript frontend framework and an alternative to React, Vue.js and Angular. Svelte comes with an integration package called SvelteKit that adds a standard web server, routing, server-side rendering and other core functionality needed to build a fully functional website.
We considered React for Trading Strategy . React is the de facto frontend framework choice of the cryptocurrency industry. However, even with our extensive experience in React, we chose Svelte because we believe Svelte is the framework of the future. Svelte offers reactivity with ahead-of-time compiled virtual DOM free approach. Svelte components are very maintanable single files, containing normal HTML template and normal CSS code instead of bastardized “styles-in-JS” or domain-specific templating approaches. Writing reactive logic in Svelte is easier than in other frameworks, due to its elegant design making the most developer-friendly frontend framework.
SvelteKit takes the developer experience of Svelte even further, by introducing the concepts of file-system based routing, simple server-side rendering and integrated web server (Vite). With SvelteKit’s batteries included approach an application developer spends less time on plumbing, boilerplate code and debugging async reactivity mess This all translates to better efficiency: the codebase is easier to read and maintain due to standardized coding conventions across open source libraries, components are faster to develop and new developers pick up the pace faster.
We also use components outside Svelte. We use uPlot for charting. Though the TradingView is the most popular JS framework for technical trading, we are puritans that go with 100% open-source approach as we are building for long term. uPlot was the charting library with an open-source license. For our number heavy tables we use DataTable library. For Web3 integration, we use web3.js through svelte-web3.
Backend: Why did we choose Python, Pyramid and SQLAlchemy?
Pyramid is a web framework for Python and SQLAlchemy is Python’s most popular ORM. We have experience writing Python applications since 2006 using Django, Flask and Pyramid. We also have experience writing backends in Node.js with various frameworks like Next.js.
For developers who know several programming languages, Python is superior choice for the backend. Writing Python programs takes fewer keystrokes. Python is the most readable of all programming languages. Optional typing support is a great way to make the code more static when the team grows.
There is a forever battle with sync vs. async. There is greater maintenance efficiency with colored function free, linear threaded, Python code. Our workloads are computationally sensitive, not IO sensitive, so using async IO would cause more headaches and we would get no benefits out of it.
We chose Pyramid and SQLAlchemy because we are doing API first backend and complex databasing with our special workload. Trading Strategy currently features tracking of 800k trading pairs (NASDAQ has only 3000). This is not your run of the mill CRUD and admin UI application. For this kind of use case, Pyramid and SQLALchemy are the choice today. This framework combo offers powerful tooling to cover advanced use cases without sacrificing developer productivity or being completely outside of an average backend developer skillset.
For our API tooling and developer communications we chose OpenAPI 3, also known as Swagger. Integration is mostly cost-free: pyramid_openapi3 validates the API definition, validates requests and replies, and can automatically route payloads to their corresponding endpoints and offers Swagger interactive API explorer. This all saves us a lot of manual development.
For background workers, we use Dramatiq library with Redis broker. Dramatiq task server is simpler, much easier to understand and maintain than more well-known Celery.
Data research: Why did we choose Jupyter notebook?
Most quantitative finance in the world uses Jupyter Notebooks and Python data science libraries like Pandas and Numpy. This is the strongest suite of Python that no other programming language can match. In fact, Pandas was originally developed by an investment bank.
Trading Strategy algorithm backtesting is done in Jupyter. We offer a Trading Strategy client library so that quants can develop their algos against decentralised exchanges without need to know low level blockchain specific details. If you are interested to see if you can beat the market please see Getting started tutorial (beta warning: better to join our Discord as well.)
Database: Why did we choose TimescaleDB?
TimescaleDB is a PostgreSQL extension specialised in time-series data, especially the “big” flavour of it. The alternatives included Clickhouse and xxx.
We chose TimescaleDB, because they are based on PostgreSQL. During the last 20 years, PostgreSQL has overtaken as the most advanced open-source database. PostgreSQL has the most vibrant database ecosystem on this planet. Tuning PostgreSQL is well-known: there are multiple products and companies to support in-house development.
Many of the core TimescaleDB features make our life easier. For example, hypertables provide fast insert times on large time-series datasets – otherwise inserting your one-billionth row starts to slow down. Continuous aggregates give us free upsampling 1-minute OHLCV candles to 5 minutes to 30 days periods.
TimescaleDB completed their Series B funding round where they raise $40M. Based on the quality of their product, the detail they go in their developer communications, we can see why they could be the winning horse of time-series databases.
TimescaleDB team has been the most responsive of any projects we have seen during the 25 years of open-source involvement. Their proactivity and helpfulness give us an assurance that TimescaleDB is serious about building an open-source community. All of our StackOveflow questions and Github issue reports, no matter how bad or novice has gone unanswered. We are pretty sure if one were to ask something offtopic, like making a coffee, and tagging with “timescaledb” it would still a receive perfect answer.
Why did we launch on Ethereum mainnet, Binance Smart Chain and Polygon?
When we started to build Trading Strategy early 2021, the layer 1 blockchains were not still on such rampage as they are today. Polygon and Binance Smart Chain were the layer 1 top dogs and no layer two was live yet. Ther chains had user adoption and active DEXes like PancakeSwap and QuickSwap. Today we have more competition with the likes of Avalanche, Fantom, Aurora and Telos EVM. Also we have non-EVM based solid solutions like NEAR, Elrond and Solana. We expect to integrate all of them during the source of 2022.
Ethereum mainnet has the best developer community. However, the Ethereum mainnet transaction costs are prohibitively expensive for the unforeseeable future, and thus it is unsuitable for our active trading strategies.
What challenges do we see?
Developing the means failing and retrying a few times, as your first guess is not always right one. We have some good lessons from 2021.
SvelteKit is still in beta. Some of the aspects of it are still under development and may not have complete documentation or supporting material like tutorial blog posts. We had to figure out a lot of aspects ourselves, especially what comes to SvelteKit server-side rendering speed and tuning. We feel the benefits of SvelteKit developer productivity greatly outweighs some learning curve and contributions to the documentation we had to do ourselves.
Svelte is new, thus it still does not have Svelte-native feature-rich charting libraries like uPlot and Datatables. They do not integrate to SvelteKit server-side rendering flow, making it not possible to serve pre-rendered pages.
Hosting Polygon and Binance Smart Chain nodes is tough. Both blockchain teams have issues with developer communications. There are no adequate manuals for running your own node. The expectation of using bug-ridden third-party API services goes against the blockchain ethos
Some queries on PostgreSQL are still unnecessary complex whereas other databases do better. Often we need to refer to the latest value, like the latest price, either for a single item or for a group. Unfortunately PostgreSQL does not offer any native “latest value” indices and it is often tricky to write an efficient query for this. Sometimes even simple ORDER LIMIT 1 seems to cause issues for PostgreSQL unless you create unnecessary fat indices.
We are open source
Trading Strategy frontend has been open source since the day one. If you are new to Svelte / SvelteKit you might find our repository interesting to read and learn why we have made certain design choices.
The same goes for the Jupyter Python trading strategy client. Oracle code and backend code will be eventually opened, as we start rolling out the protocol network later in 2022.
We are hiring
We are currently hiring for frontend (Svelte), backend (Python/PostgreSQL) and quant research (Jupytere Notebook/Pandas) positions. If you are interested to work with cryptocurrencies and algorithmic trading please email us careers@tradingstrategy.ai.
The cover photo by Alex Chumak.
Subscribe to RSS feed
Follow me on Twitter
Follow me on Facebook
Follow me Google+
January 07, 2022 12:02 PM UTC
A year ago, we had Brett Cannon on the show to discuss his blog series about unravelling Python's syntactic sugar. Brett has written 15 more entries in the series, and he returns to the show this week to continue our conversation. We dive into unravelling 'async' and 'await' statements and their relationship with Python's generators.
[ 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 ]
January 07, 2022 12:00 PM UTC
This post is the repost of the original Trading Strategy software architecture overview for community feed aggregators. Please read the original post for the best layout and formatting.
The audience of this post is software developers who are looking to build scalable software-as-a-service solutions and are interested in Svelte, Python and TimescaleDB technologies. Developers who are interested in Web3, Ethereum, cryptocurrency and blockchain technologies will also find this post useful.
What are Trading Strategy protocol and algorithmic trading?
Trading Strategy is a new service for algorithmic and technical trading of cryptocurrencies on decentralised exchange (DEXes).
Algorithmic trading is a derivative of technical analysis; taking trading positions based on pure mathematics and data. Algorithmic trading is part of quantitative finance, the opposite of value investing where trading decisions are made based on fundamentals. Algorithmic trading provides a systematic approach to trading compared to methods based on trader intuition or instinct. Whereas technical analysis often aids humans to take trading positions, in its purest form in algorithmic trading a trading program follows a set of trading rules and independently executes trades on the market 24/7.
Today, Trading Strategy offers market data feeds for Uniswap compatible exchanges across three different blockchains (Ethereum, Binance Smart Chain, Polygon). We expect to cover all major decentralised exchanges and exchange types on all major blockchains by the end of the year.
Our mission is to make algorithmic by developing and investing in algorithmic trading strategies easy. Although serving the market data is the first step, Trading Strategy is going to grow beyond the information service website. During the course of 2022, the service will be decentralised, so that the whole software solution, strategy and trade execution will be runnable anyone independently (so-called operating a node).
You can read more about our future plans in our vision blog post.
Rich in technical wealth
Trading Strategy chose modern architecture and the best components of 2021 for its software development, making its codebase high in technical wealth.
Technical wealth is the opposite of technical debt. As Trading Strategy was able to start as a clean slate project, we had the privilege to pick the latest technologies and build our architecture around these. This enables us to build faster and do changes more dynamically. As an example, a lot of out of the box features offered by TimescaleDB would have taken us months if we had built them ourselves.
The decentralised finance (DeFi) industry itself is high in technical wealth compared to traditional finance (TradFi). This is due to the use of public ledger (open data), free-as-in-speech codebases (open source) and permissionless public blockchains (open access). This is the opposite of the traditional financial services that are built around closed networks, private APIs and exclusive access. Privileged and siloed software development leads to high maintenance cost long term, as there are no people who are able to work with the code. For references, see this blog post on legacy investment bank software and Google’s woes about maintaining their own Linux kernel with 9000+ in-house patches. Writing financial applications for DeFi is 10x – 100x more developer productive than writing them for TradFi.
What is a Web3?
From the software developer point of view, Web3 refers to backend-free services. No logins or registrations are needed. The user data is not processed and stored on a private server, but a public blockchain where the business logic is wired together using smart contracts. Any transaction, or a “POST request” in the traditional parlay, is initiated by users themselves, using their private key on their locally stored wallet application.
In this kind of model, there are no sysadmin fraud risks, no data loss risks or data liability risks with user identity information. The user is in 100% control. It is a fairer world where users have more control over the revenue streams they generate. Big IT like Facebook and Google have fewer unfair monetization opportunities on user data.
Only some services are a good fit for Web3. At the moment Web3 works best for pseudonymous and public data use cases. This is almost all finance, provenance (NFTs), public social media like Twitter and discussion forums and eCommerce.
Web3 is still early: though most pieces have been figured out in computer science theory, the implementation is still under development. For example, doing database-like traffic (ThreadDB) and storage (Arweave, Storj) can be still considered “alpha” today.
Software stack overview
Below is a walkthrough of how the HTTP requesting of Trading Strategy website is set up. Because Trading Strategy application is eventually going to be a Web3-like oracle node in a distributed network, everything built API first. There are no internal APIs – the website uses the same public market data APIs as everyone else.
Trading Strategy Oracle is a process that indexes blockchain data: DEX trading data, tokens and so on. Oracle and web processes communicate over TimescaleDB. Oracle is responsible for tasks like generating OHLCV candle data, generating liquidity maps and fetching US dollar reference prices. Oracle processes connect to various blockchain GoEthereum nodes that are part of the P2P network for the respective Ethereum Virtual Machine based blockchains.
Frontend: Why did we choose Svelte?
Svelte is a new JavaScript frontend framework and an alternative to React, Vue.js and Angular. Svelte comes with an integration package called SvelteKit that adds a standard web server, routing, server-side rendering and other core functionality needed to build a fully functional website.
We considered React for Trading Strategy . React is the de facto frontend framework choice of the cryptocurrency industry. However, even with our extensive experience in React, we chose Svelte because we believe Svelte is the framework of the future. Svelte offers reactivity with ahead-of-time compiled virtual DOM free approach. Svelte components are very maintanable single files, containing normal HTML template and normal CSS code instead of bastardized “styles-in-JS” or domain-specific templating approaches. Writing reactive logic in Svelte is easier than in other frameworks, due to its elegant design making the most developer-friendly frontend framework.
SvelteKit takes the developer experience of Svelte even further, by introducing the concepts of file-system based routing, simple server-side rendering and integrated web server (Vite). With SvelteKit’s batteries included approach an application developer spends less time on plumbing, boilerplate code and debugging async reactivity mess This all translates to better efficiency: the codebase is easier to read and maintain due to standardized coding conventions across open source libraries, components are faster to develop and new developers pick up the pace faster.
We also use components outside Svelte. We use uPlot for charting. Though the TradingView is the most popular JS framework for technical trading, we are puritans that go with 100% open-source approach as we are building for long term. uPlot was the charting library with an open-source license. For our number heavy tables we use DataTable library. For Web3 integration, we use web3.js through svelte-web3.
Backend: Why did we choose Python, Pyramid and SQLAlchemy?
Pyramid is a web framework for Python and SQLAlchemy is Python’s most popular ORM. We have experience writing Python applications since 2006 using Django, Flask and Pyramid. We also have experience writing backends in Node.js with various frameworks like Next.js.
For developers who know several programming languages, Python is superior choice for the backend. Writing Python programs takes fewer keystrokes. Python is the most readable of all programming languages. Optional typing support is a great way to make the code more static when the team grows.
There is a forever battle with sync vs. async. There is greater maintenance efficiency with colored function free, linear threaded, Python code. Our workloads are computationally sensitive, not IO sensitive, so using async IO would cause more headaches and we would get no benefits out of it.
We chose Pyramid and SQLAlchemy because we are doing API first backend and complex databasing with our special workload. Trading Strategy currently features tracking of 800k trading pairs (NASDAQ has only 3000). This is not your run of the mill CRUD and admin UI application. For this kind of use case, Pyramid and SQLALchemy are the choice today. This framework combo offers powerful tooling to cover advanced use cases without sacrificing developer productivity or being completely outside of an average backend developer skillset.
For our API tooling and developer communications we chose OpenAPI 3, also known as Swagger. Integration is mostly cost-free: pyramid_openapi3 validates the API definition, validates requests and replies, and can automatically route payloads to their corresponding endpoints and offers Swagger interactive API explorer. This all saves us a lot of manual development.
For background workers, we use Dramatiq library with Redis broker. Dramatiq task server is simpler, much easier to understand and maintain than more well-known Celery.
Data research: Why did we choose Jupyter notebook?
Most quantitative finance in the world uses Jupyter Notebooks and Python data science libraries like Pandas and Numpy. This is the strongest suite of Python that no other programming language can match. In fact, Pandas was originally developed by an investment bank.
Trading Strategy algorithm backtesting is done in Jupyter. We offer a Trading Strategy client library so that quants can develop their algos against decentralised exchanges without need to know low level blockchain specific details. If you are interested to see if you can beat the market please see Getting started tutorial (beta warning: better to join our Discord as well.)
Database: Why did we choose TimescaleDB?
TimescaleDB is a PostgreSQL extension specialised in time-series data, especially the “big” flavour of it. The alternatives included Clickhouse and xxx.
We chose TimescaleDB, because they are based on PostgreSQL. During the last 20 years, PostgreSQL has overtaken as the most advanced open-source database. PostgreSQL has the most vibrant database ecosystem on this planet. Tuning PostgreSQL is well-known: there are multiple products and companies to support in-house development.
Many of the core TimescaleDB features make our life easier. For example, hypertables provide fast insert times on large time-series datasets – otherwise inserting your one-billionth row starts to slow down. Continuous aggregates give us free upsampling 1-minute OHLCV candles to 5 minutes to 30 days periods.
TimescaleDB completed their Series B funding round where they raise $40M. Based on the quality of their product, the detail they go in their developer communications, we can see why they could be the winning horse of time-series databases.
TimescaleDB team has been the most responsive of any projects we have seen during the 25 years of open-source involvement. Their proactivity and helpfulness give us an assurance that TimescaleDB is serious about building an open-source community. All of our StackOveflow questions and Github issue reports, no matter how bad or novice has gone unanswered. We are pretty sure if one were to ask something offtopic, like making a coffee, and tagging with “timescaledb” it would still a receive perfect answer.
Why did we launch on Ethereum mainnet, Binance Smart Chain and Polygon?
When we started to build Trading Strategy early 2021, the layer 1 blockchains were not still on such rampage as they are today. Polygon and Binance Smart Chain were the layer 1 top dogs and no layer two was live yet. Ther chains had user adoption and active DEXes like PancakeSwap and QuickSwap. Today we have more competition with the likes of Avalanche, Fantom, Aurora and Telos EVM. Also we have non-EVM based solid solutions like NEAR, Elrond and Solana. We expect to integrate all of them during the source of 2022.
Ethereum mainnet has the best developer community. However, the Ethereum mainnet transaction costs are prohibitively expensive for the unforeseeable future, and thus it is unsuitable for our active trading strategies.
What challenges do we see?
Developing the means failing and retrying a few times, as your first guess is not always right one. We have some good lessons from 2021.
SvelteKit is still in beta. Some of the aspects of it are still under development and may not have complete documentation or supporting material like tutorial blog posts. We had to figure out a lot of aspects ourselves, especially what comes to SvelteKit server-side rendering speed and tuning. We feel the benefits of SvelteKit developer productivity greatly outweighs some learning curve and contributions to the documentation we had to do ourselves.
Svelte is new, thus it still does not have Svelte-native feature-rich charting libraries like uPlot and Datatables. They do not integrate to SvelteKit server-side rendering flow, making it not possible to serve pre-rendered pages.
Hosting Polygon and Binance Smart Chain nodes is tough. Both blockchain teams have issues with developer communications. There are no adequate manuals for running your own node. The expectation of using bug-ridden third-party API services goes against the blockchain ethos
Some queries on PostgreSQL are still unnecessary complex whereas other databases do better. Often we need to refer to the latest value, like the latest price, either for a single item or for a group. Unfortunately PostgreSQL does not offer any native “latest value” indices and it is often tricky to write an efficient query for this. Sometimes even simple ORDER LIMIT 1 seems to cause issues for PostgreSQL unless you create unnecessary fat indices.
We are open source
Trading Strategy frontend has been open source since the day one. If you are new to Svelte / SvelteKit you might find our repository interesting to read and learn why we have made certain design choices.
The same goes for the Jupyter Python trading strategy client. Oracle code and backend code will be eventually opened, as we start rolling out the protocol network later in 2022.
We are hiring
We are currently hiring for frontend (Svelte), backend (Python/PostgreSQL) and quant research (Jupytere Notebook/Pandas) positions. If you are interested to work with cryptocurrencies and algorithmic trading please email us careers@tradingstrategy.ai.
The cover photo by Alex Chumak.
January 07, 2022 11:59 AM UTC
This week I released the first version of Tumpa on
Mac. Though the
actual changes required for building the Mac app and dmg file were small, but
I had to reap apart those few remaining hairs on my head to get it working on
any other Mac (than the building box). It was the classic case of Works on my
laptop.
The issue
Tumpa is a Python application which uses PySide2 and also
Johnnycanencrypt which is written in Rust.
I tried both briefcase tool and
manual calling to codesign and create-dmg tools to create the tumpa.app
and the tumpa-0.1.3.dmg.
After creating the dmg file, I had to submit it for notarisation to Apple,
following:
xcrun /Applications/Xcode.app/Contents/Developer/usr/bin/altool --notarize-app --primary-bundle-id "in.kushaldas.Tumpa" -u "kushaldas@gmail.com" -p "@keychain:MYNOTARIZATION" -f macOS/tumpa-0.1.3.dmg
This worked successfully, after a few minutes I can see that the job passed. So, I can then staple the ticket on the dmg file.
xcrun stapler staple macOS/tumpa-0.1.3.dmg
I can install from the file, and run the application, sounds great.
But, whenever someone else tried to run the application after installing from
dmg, it showed the following.

Solution
It took me over 4 hours to keep trying all possible combinations, and finally I
had to pass --options=runtime,library to the codesign tool, and that did
the trick. Not being able to figure out how to get more logs on Mac was making
my life difficult.
I had to patch briefcase to make sure I can keep using it (also created the
upstream issue).
--- .venv/lib/python3.9/site-packages/briefcase/platforms/macOS/__init__.py 2022-01-07 08:48:12.000000000 +0100
+++ /tmp/__init__.py 2022-01-07 08:47:54.000000000 +0100
@@ -117,7 +117,7 @@
'--deep', str(path),
'--force',
'--timestamp',
- '--options', 'runtime',
+ '--options', 'runtime,library',
],
check=True,
)
You can see my build
script,
which is based on input from Micah.
I want to thank all of my new friends inside of SUNET who
were excellent helping hands to test the multiple builds of Tumpa. Later many
folks from IRC also jumped in to help to test the tool.
January 07, 2022 09:10 AM UTC
Yesterday I wrote about how to use the
Any type in Rust to implement extension maps. One thing that was
brought up as a response is that it's hard to implement Debug for the
extension map as Any does not implement Debug. The challenge is that
unfortunately in Rust you cannot do Box<dyn Any + Debug>. However
there are ways around it.
The Simplifed Problem
Let's say you want to have a wrapper around a boxed any that you can
debug. This is what we basically want to accomplish:
#[derive(Debug)]
struct AnyBox(Box<dyn Any + Debug>);
If we were to compile this, the compiler doesn't come back happy:
error[E0225]: only auto traits can be used as additional traits in a trait object
--> src/main.rs:9:29
|
9 | struct AnyBox(Box<dyn Any + Debug>);
| --- ^^^^^ additional non-auto trait
| |
| first non-auto trait
|
= help: consider creating a new trait with all of these as supertraits and
using that trait here instead: `trait NewTrait: Any + Debug {}`
Supertraits
Thankfully the compiler actually tells is what the solution is: we need to
create a new super trait that we can use. However it leaves us a bit in
the dark of how to do this successfully. Basically we want to implement
our super trait for all types implementing the individual traits.
Something like this:
#[derive(Debug)]
struct AnyBox(Box<dyn Any + Debug>);
trait DebugAny: Any + Debug {}
impl<T: Any + Debug + 'static> DebugAny for T {}
This will in fact compile and you will be able to construct such a box,
but what will not work is downcasting:
fn main() {
let any_box = AnyBox(Box::new(42i32));
dbg!(any_box.0.downcast_ref::<i32>());
}
The compiler will tell us that our value in the anybox has no method named
downcast_ref:
error[E0599]: no method named `downcast_ref` found for struct
`Box<(dyn DebugAny + 'static)>` in the current scope
--> src/main.rs:15:20
|
15 | dbg!(any_box.0.downcast_ref::<i32>());
| ^^^^^^^^^^^^ method not found in `Box<(dyn DebugAny + 'static)>`
The reason for this is that a Box<dyn DebugAny> unfortunately is not a
Box<dyn Any> and as such we don't get the methods from it that we
need. So how do we fix this? The simplest method is the “as any” pattern
where we implement a method on our DebugAny trait that upcasts into an
Any. This looks like this:
trait DebugAny: Any + Debug {
fn as_any(&self) -> &dyn Any;
fn as_any_mut(&mut self) -> &mut dyn Any;
}
impl<T: Any + Debug + 'static> DebugAny for T {
fn as_any(&self) -> &dyn Any { self }
fn as_any_mut(&mut self) -> &mut dyn Any { self }
}
Now we still can't downcast_ref on the box, but we can take our value,
call as_any on it, retrieve a &dyn Any and then go to town:
fn main() {
let any_box = AnyBox(Box::new(42i32));
dbg!(any_box.0.as_any().downcast_ref::<i32>());
dbg!(&any_box);
}
Except if we run it, we get None. What's going on?
[src/main.rs:23] any_box.0.as_any().downcast_ref::<i32>() = None
The answer to this riddle has to do with how the method resolution works
and blanket implementations. When we invoke as_any on Box<dyn
DebugAny> we're not looking through the box, we're in fact invoking
as_any on the Box<dyn DebugAny> itself since the box also implements
our DebugAny now. So how do we reach through the box? By dereferencing
it.
fn main() {
let any_box = AnyBox(Box::new(42i32));
dbg!((*any_box.0).as_any().downcast_ref::<i32>());
dbg!(&any_box);
}
And now we get what we expect:
[src/main.rs:23] (*any_box.0).as_any().downcast_ref::<i32>() = Some(
42,
)
[src/main.rs:24] &any_box = AnyBox(
42,
)
Debuggable Extension Map
These learnings we can now take back to building an extension map which
can be debug printed. Let's take the non sync extension map from last
time and modify it so we can debug
print it:
use std::any::{Any, TypeId};
use std::cell::{Ref, RefCell, RefMut};
use std::collections::HashMap;
use std::fmt::Debug;
trait DebugAny: Any + Debug {
fn as_any(&self) -> &dyn Any;
fn as_any_mut(&mut self) -> &mut dyn Any;
}
impl<T: Any + Debug + 'static> DebugAny for T {
fn as_any(&self) -> &dyn Any { self }
fn as_any_mut(&mut self) -> &mut dyn Any { self }
}
#[derive(Default, Debug)]
pub struct Extensions {
map: RefCell<HashMap<TypeId, Box<dyn DebugAny>>>,
}
impl Extensions {
pub fn insert<T: Debug + 'static>(&self, value: T) {
self.map
.borrow_mut()
.insert(TypeId::of::<T>(), Box::new(value));
}
pub fn get<T: Default + Debug + 'static>(&self) -> Ref<'_, T> {
self.ensure::<T>();
Ref::map(self.map.borrow(), |m| {
m.get(&TypeId::of::<T>())
.and_then(|b| (**b).as_any().downcast_ref())
.unwrap()
})
}
pub fn get_mut<T: Default + Debug + 'static>(&self) -> RefMut<'_, T> {
self.ensure::<T>();
RefMut::map(self.map.borrow_mut(), |m| {
m.get_mut(&TypeId::of::<T>())
.and_then(|b| (**b).as_any_mut().downcast_mut())
.unwrap()
})
}
fn ensure<T: Default + Debug + 'static>(&self) {
if self.map.borrow().get(&TypeId::of::<T>()).is_none() {
self.insert(T::default());
}
}
}
Adding some stuff into the map and debug printing it makes it output
something like this now:
[src/main.rs:63] &extensions = Extensions {
map: RefCell {
value: {
TypeId {
t: 13431306602944299956,
}: 42,
},
},
}
In this case I placed a 32bit integer 42 in the map and we can see
that it prints out the type id of that as key, and 42 as value.
Retaining Type Names
If we want to retain the original type name and not just type ID we could
change our TypeId key for a custom type which also stores the original
type name. This could be accomplished by creating a wrapper for our
TypeId which uses std::any::type_name internally:
use std::any::{TypeId, type_name};
use std::hash::{Hash, Hasher};
use std::fmt::{self, Debug};
pub struct TypeKey(TypeId, &'static str);
impl TypeKey {
pub fn of<T: 'static>() -> TypeKey {
TypeKey(TypeId::of::<T>(), type_name::<T>())
}
}
impl Hash for TypeKey {
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.hash(state);
}
}
impl PartialEq for TypeKey {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
impl Eq for TypeKey {}
impl Debug for TypeKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.1)
}
}
Now we can replace our use of TypeId with TypeKey in the extension map
and our debug output looks like this instead:
[src/main.rs:90] &extensions = Extensions {
map: RefCell {
value: {
i32: 42,
alloc::vec::Vec<i32>: [
1,
2,
3,
],
},
},
}
Note that i additionally inserted a Vec<i32> into the map to get some
more extra output.
January 07, 2022 12:00 AM UTC
January 06, 2022
You might have studied functions in python. You might also have used for loops and while loops to perform a task repetitively while programming in Python. In this article, we will discuss recursion and recursive functions in Python.
What Is Recursion?
Recursion is a mathematical concept in which we define something in terms of itself.
For instance, we can define the sum of the first ten natural numbers as the sum of the first nine natural numbers added to the tenth number.
Similarly, we can define the sum of the first nine natural numbers as the sum of the first eight natural numbers added to the ninth natural number.
Here, you can see that we are breaking the problem of the first ten natural numbers into smaller problems like finding the sum of the first 9 numbers, then finding the sum of the first 8 numbers, and so on. In this way, we will come to a position where we have to find the sum of the first natural number i.e. 1 itself. After that, we will have to perform only the atomic addition instead of worrying about the count of natural numbers we are finding the sum of.
When To Use Recursion In Python?
As seen above, we can use recursion whenever we can break a problem into a similar but smaller problem. The most common problems where we use recursion are:
- Binary tree traversal problems
- Finding the factorial of a number
- Tower of Hanoi problem
- Finding Fibonacci series
How To Use Recursion In Python?
In programming, if a function calls itself, we say that it is a recursive function i.e. it works on the concept of recursion. You can use recursion in python to implement the solution for any problem that can be reduced to a similar but smaller problem.
For instance, let us try to find the sum of the first 10 natural numbers. For that, let us define a function sumOfNumbers() that receives an input number N and returns the sum of numbers from 1 to N.
- To calculate the sum of first 10 natural numbers i.e. sumOfNumbers(10), we will find the sum of the first 9 natural numbers i.e. sumOfNumbers(9) and will add 10 to it.
- Similarly, to find the sum of first 9 natural numbers i.e. sumOfNumbers(9), we will find the sum of the first 8 natural numbers i.e. sumOfNumbers(8) and will add 9 to it.
- Again, to find the sum of the first 8 natural numbers i.e. sumOfNumbers(8), we will find the sum of the first 7 natural numbers i.e. sumOfNumbers(7) and will add 8 to it.
- After that, to find the sum of the first 7 natural numbers i.e. sumOfNumbers(7), we will find the sum of the first 6 natural numbers i.e. sumOfNumbers(6) and will add 7 to it.
- In this way, we will reach a position when we will have to calculate the sum of the first natural number i.e. sumOfNumbers(1). Here, we can simply return 1. This is also called the base case of the recursion as the problem cannot be reduced further into smaller problems.
We can implement the above algorithm as follows.
def sumOfNumbers(N):
if N == 1:
return N
else:
return N + sumOfNumbers(N - 1)
input_number = 10
output = sumOfNumbers(input_number)
print("Sum of first {} natural numbers is {}".format(input_number, output))
input_number = 20
output = sumOfNumbers(input_number)
print("Sum of first {} natural numbers is {}".format(input_number, output))
Output:
Sum of first 10 natural numbers is 55
Sum of first 20 natural numbers is 210
While using recursion, we must specify the base case. Otherwise, the program will continue its execution continuously and run into RecursionError. This is due to the fact that the maximum number of recursive calls a function can make is capped at 1000 in Python. If any function makes more than 1000 recursive calls, a RecursionError exception will occur.
Conclusion
In this article, we have discussed recursion in python. We have also implemented a program to find the sum of the first 10 natural numbers in Python. To learn more about functions, you can read this article on closures in python.
The post Recursion In Python appeared first on PythonForBeginners.com.
January 06, 2022 02:10 PM UTC