Quantcast
Channel: Planet Python
Viewing all 22422 articles
Browse latest View live

Test and Code: 106: Visual Testing : How IDEs can make software testing easier - Paul Everitt

$
0
0

IDEs can help people with automated testing.

In this episode, Paul Everitt and Brian discuss ways IDEs can encourage testing and make it easier for everyone, including beginners. We discuss features that exist and are great, as well as what is missing.

The conversation also includes topics around being welcoming to new contributors for both open source and professional projects.

We talk about a lot of topics, and it's a lot of fun. But it's also important. Because IDEs can make testing

Some topics discussed:

  • Making testing more accessible
  • Test First vs teaching testing last
  • TDD workflow
  • Autorun
  • Rerunning last failures
  • Different ways to run different levels of tests
  • Command line flags and how to access them in IDEs
  • pytest.ini
  • zooming in and out of test levels
  • running parametrizations
  • running tests with coverage and profiling
  • parametrize vs parameterize
  • parametrization identifiers
  • pytest fixture support
  • global configurations / configuration templates
  • coverage and testing and being inviting to new contributors
  • confidence in changes and confidence in contributions
  • navigating code, tests, fixtures
  • grouping tests in modules, classes, directories
  • BDD, behavior driven development, cucumber, pytest-bdd
  • web development testing
  • parallel testing with xdist and IDE support
  • refactor rename

Special Guest: Paul Everitt.

Support Test & Code : Python Testing for Software Engineers

Links:

<p>IDEs can help people with automated testing.</p> <p>In this episode, Paul Everitt and Brian discuss ways IDEs can encourage testing and make it easier for everyone, including beginners. We discuss features that exist and are great, as well as what is missing.</p> <p>The conversation also includes topics around being welcoming to new contributors for both open source and professional projects.</p> <p>We talk about a lot of topics, and it&#39;s a lot of fun. But it&#39;s also important. Because IDEs can make testing </p> <p>Some topics discussed:</p> <ul> <li>Making testing more accessible</li> <li>Test First vs teaching testing last</li> <li>TDD workflow</li> <li>Autorun</li> <li>Rerunning last failures</li> <li>Different ways to run different levels of tests</li> <li>Command line flags and how to access them in IDEs</li> <li>pytest.ini</li> <li>zooming in and out of test levels</li> <li>running parametrizations</li> <li>running tests with coverage and profiling</li> <li>parametrize vs parameterize</li> <li>parametrization identifiers</li> <li>pytest fixture support</li> <li>global configurations / configuration templates</li> <li>coverage and testing and being inviting to new contributors</li> <li>confidence in changes and confidence in contributions</li> <li>navigating code, tests, fixtures</li> <li>grouping tests in modules, classes, directories</li> <li>BDD, behavior driven development, cucumber, pytest-bdd</li> <li>web development testing</li> <li>parallel testing with xdist and IDE support</li> <li>refactor rename</li> </ul><p>Special Guest: Paul Everitt.</p><p><a href="https://www.patreon.com/testpodcast" rel="payment">Support Test & Code : Python Testing for Software Engineers</a></p><p>Links:</p><ul><li><a href="https://amzn.to/3daFKXc" title="Python Testing with pytest" rel="nofollow">Python Testing with pytest</a> &mdash; The pytest book</li><li><a href="https://www.jetbrains.com/pycharm/" title="PyCharm" rel="nofollow">PyCharm</a></li><li><a href="https://testandcode.com/pycharm" title="PyCharm pro" rel="nofollow">PyCharm pro</a></li><li><a href="https://testandcode.com/54" title="episode 54: Python 1994 - Paul Everitt" rel="nofollow">episode 54: Python 1994 - Paul Everitt</a></li><li><a href="https://pypi.org/project/pytest-xdist/" title="pytest-xdist" rel="nofollow">pytest-xdist</a></li></ul>

Weekly Python StackOverflow Report: (ccxx) stackoverflow python report

$
0
0

Twisted Matrix Labs: Twisted 20.3.0 Released

$
0
0

On behalf of Twisted Matrix Laboratories, I am honoured to announce the release of Twisted 20.3! The highlights of this release are:

  • curve25519-sha256 key exchange algorithm support in Conch.
  • "openssh-key-v1" key format support in Conch.
  • Security fixes to twisted.web, including preventing request smuggling attacks and rejecting malformed headers. CVE-2020-10108 and CVE-2020-10109 were assigned for these issues, see the NEWS file for full details.
  • twist dns --secondary now works on Python 3.
  • The deprecation of twisted.news.
  • ...and various other fixes, with 28 tickets closed in total.

You can find the downloads at <https://pypi.org/project/Twisted> (or alternatively <https://twistedmatrix.com/trac/wiki/Downloads>). The NEWS file is also available at <https://github.com/twisted/twisted/blob/twisted-20.3.0/NEWS.rst>.

Many thanks to everyone who had a part in this release — the supporters of the Twisted Software Foundation, the developers who contributed code as well as documentation, and all the people building great things with Twisted!

- hawkowl

Python Bytes: #173 Your test deserves a fluent flavor

$
0
0
<p>Sponsored by Datadog: <a href="http://pythonbytes.fm/datadog"><strong>pythonbytes.fm/datadog</strong></a></p> <p><strong>Brian #1:</strong> <a href="https://hodovi.ch/blog/advanced-usage-python-requests-timeouts-retries-hooks/"><strong>Advanced usage of Python requests - timeouts, retries, hooks</strong></a></p> <ul> <li>Dani Hodovic, <a href="https://twitter.com/DaniHodovic">@DaniHodovic</a></li> <li>“While it's easy to immediately be productive with requests because of the simple API, the library also offers extensibility for advanced use cases. If you're writing an API-heavy client or a web scraper you'll probably need tolerance for network failures, helpful debugging traces and syntactic sugar.”</li> <li>Lots of cool tricks I didn’t know you could do with requests. <ul> <li>Using hooks to call <code>raise_for_status()</code> on every call.</li> <li>Using sessions and setting base URLs</li> <li>Setting default timeouts with transport adapters</li> <li>Retry on failure, with gobs of configuration options.</li> <li>Combining timeouts and retries</li> <li>Debugging http requests by printing out headers or printing everything.</li> <li>Testing and mocking requests</li> <li>Mimicking browser behaviors by overriding the User-Agent header request</li> </ul></li> </ul> <p><strong>Michael #2:</strong> <a href="https://github.com/csparpa/fluentcheck">Fluent Assertions</a></p> <ul> <li>Via <a href="https://twitter.com/dean_agan/status/1236231021416202240">Dean Agan</a></li> <li><strong>fluentcheck</strong> helps you reducing the lines of code providing a human-friendly and fluent way to make assertions.</li> <li>Example (for now):</li> </ul> <pre><code>def my_function(n, obj): assert n is not None assert instanceof(n, float) assert 0. &lt; n &lt; 1 assert obj is not None assert isinstance(obj, MyCustomType) </code></pre> <p>can be</p> <pre><code>def my_function(n, obj): Check(n).is_not_None().is_float().is_between(0., 1.) Check(obj).is_not_None().is_subtype_of(MyCustomType) </code></pre> <p>With <a href="https://github.com/csparpa/fluentcheck/pull/14">a PR I’m working on</a> (now accepted), it’ll support:</p> <pre><code>def my_function(n, obj): Is(n).not_none.float.between(0., 1.) Is(obj).not_none.subtype_of(MyCustomType) </code></pre> <p><strong>Brian #3:</strong> <a href="https://hynek.me/articles/python-github-actions/"><strong>Python in GitHub Actions</strong></a></p> <ul> <li>Hynek Schlawack, <a href="https://twitter.com/hynek">@hynek</a></li> <li>“for an open source Python package, … my current recommendation for most people is to switch to GitHub Actions for its simplicity and better integration.” vs Azure Pipelines.</li> <li>Article describes how to get started and some basic configuration for: <ul> <li>Running tests through tox, including coverage, for multiple Python versions. Including yml config and tox.ini changes necessary.</li> <li>Nice reminder to clean out old configurations for other CIs.</li> <li>Combining coverage reports and pushing code coverage info to Codecov</li> <li>Building the package.</li> <li>Running twine check to check the long description.</li> <li>Checking the install on Linux, Windows, and Mac</li> </ul></li> <li>Related: <ul> <li><a href="https://medium.com/@wkrzywiec/how-to-write-good-quality-python-code-with-github-actions-2f635a2ab09a">How to write good quality Python code with GitHub Actions</a></li> </ul></li> </ul> <p><strong>Michael #4:</strong> <a href="https://vcrpy.readthedocs.io/en/latest/"><strong>VCR.py</strong></a></p> <ul> <li>via Tim Head</li> <li>VCR.py simplifies and speeds up tests that make HTTP requests. </li> <li>The first time you run code that is inside a VCR.py context manager or decorated function, VCR.py records all HTTP interactions that take place through the libraries it supports and serializes and writes them to a flat file (in yaml format by default). </li> <li>Intercept any HTTP requests that it recognizes from the original test run and return the responses that corresponded to those requests. This means that the requests will not actually result in HTTP traffic, which confers several benefits including: <ul> <li>The ability to work offline</li> <li>Completely deterministic tests</li> <li>Increased test execution speed</li> </ul></li> <li>If the server you are testing against ever changes its API, all you need to do is delete your existing cassette files, and run your tests again.</li> <li><a href="https://testandcode.com/102">Test and Code 102</a></li> <li><a href="https://github.com/ktosiek/pytest-vcr">pytest-vcr</a>: pytest plugin for managing VCR.py cassettes</li> </ul> <pre><code>@pytest.mark.vcr() def test_iana(): response = urlopen('http://iana.org/domains/reserved').read() assert b'Example domains' in response </code></pre> <p><strong>Brian #5:</strong> <a href="https://dev.to/renegadecoder94/8-coolest-python-programming-language-features-58i9"><strong>8 Coolest Python Programming Language Features</strong></a></p> <ul> <li>Jeremy Grifski, <a href="http://twitter.com/RenegadeCoder94">@RenegadeCoder94</a></li> <li>Nice reminder of why I love Python and things I miss when I use other languages.</li> <li>The list <ul> <li>list comprehensions</li> <li>generator expressions</li> <li>slice assignment</li> <li>iterable unpacking</li> <li>negative indexing</li> <li>dictionary comprehensions</li> <li>chaining comparisons</li> <li>f-strings</li> </ul></li> </ul> <p><strong>Michael #6:</strong> <a href="http://bento.dev"><strong>Bento</strong></a></p> <ul> <li>Find Python web-app bugs delightfully fast, without changing your workflow</li> <li>Find bugs that matter: Checks find security and reliability bugs in your code. They’re vetted across thousands of open source projects and never nit your style.</li> <li>Upgrade your tooling: You don’t have to fix existing bugs to adopt Bento. It’s diff-centric, finding new bugs introduced by your changes. And there’s zero config.</li> <li>Go delightfully fast: Run Bento automatically locally or in CI. Either way, it runs offline and never sends your code anywhere.</li> <li>Checks: <a href="https://bento.dev/checks/">https://bento.dev/checks/</a> </li> </ul> <p><strong>Joke:</strong></p> <p><a href="https://trello-attachments.s3.amazonaws.com/58e3f7c543422d7f3ad84f33/5e5ff5b454e93258e907753b/ecd7567c50cc0d073820bf961f489365/debugging.jpg">https://trello-attachments.s3.amazonaws.com/58e3f7c543422d7f3ad84f33/5e5ff5b454e93258e907753b/ecd7567c50cc0d073820bf961f489365/debugging.jpg</a></p>

Hynek Schlawack: Hardening Your Web Server’s SSL Ciphers

$
0
0

There are many wordy articles on configuring your web server’s TLS ciphers. This is not one of them. Instead I will share a configuration which is both compatible enough for today’s needs and scores a straight “A” on Qualys’s SSL Server Test.

Mike Driscoll: PyDev of the Week: Takeshi Komiya

$
0
0

This week we welcome Komiya Takeshi as our PyDev of the Week! Takeshi is a maintainer of Sphinx, Python’s documentation package. Takeshi is also the creator of blockdiag, diagram image generator. If you are interested in seeing some of the other projects that Komiya contributes to, you should check out his Github profile.

Let’s spend some time getting to know Takeshi better!

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

I am a software engineer from Tokyo, Japan. Now I work at Time Intermedia Corp. as CTO. Time Intermedia is a systems integrator.

I love to have tea when I’m programming. I often bring my laptop to a cafe and enjoy programming all day long. My hobbies include driving all around Japan and watching football games.

Why did you start using Python?

My first contact with Python was 10+ years ago, when I took part in a local Hack-a-thon event as a staff; Zope/Plone Hack-a-thon (now renamed to Python mini Hack-a-thon). In those days, I used to mostly use Ruby for my hobby projects. I started using Python for my OSS projects since then.

My first product of Python is blockdiag. It is a converter from a text written in original syntax to block diagram image. I think it let me know to enjoy programming in OSS. Even now, I sometimes see the tweets and articles about blockdiag. I’m very happy to see them.

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

So far, I have experience in C, Perl, PHP, Ruby, and Python. If I have to choose one, I prefer to use Python. Since I started using Python, I have used it for OSS works almost every night. So I’m familiar with it.

I also love Ruby. It lets me know programming is a fan. Now I have no time to write code in Ruby. But I still like it.

What projects are you working on now?

In the last 5 years, I’ve worked on Sphinx. It is an Open Source document generator. It can build beautiful documentation in several formats. I also meet it in the Japanese Python community. After that, I made many kinds of extension packages for Sphinx. Finally, I become a maintainer of Sphinx itself.

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

Nearly every day, I need to use functools, inspect and typing modules. I feel they are very clear and cool. I learned “Pythonic” from them.

I also read docutils because Sphinx is based on it. It is a bit old, but it provides a very flexible framework for document conversion.

Why do you use Sphinx over another documentation package?

Because it’s there! TBH, I’m not a user of Sphinx, only a developer. Indeed, I’ve sometimes used it to create documents for my products. But the time I spent developing Sphinx is much longer than the time for usage.

Is there anything else you’d like to say?

Python and its community let me meet my friends. I really appreciate the great language and wonderful community. And I’d like to say “Thank you” for everyone who uses Sphinx.

The post PyDev of the Week: Takeshi Komiya appeared first on The Mouse Vs. The Python.

Erik Marsja: How to use Pandas read_html to Scrape Data from HTML Tables

$
0
0

The post How to use Pandas read_html to Scrape Data from HTML Tables appeared first on Erik Marsja.

In this Pandas tutorial, we will go through the steps on how to use Pandas read_html method for scraping data from HTML. First, in the simplest example, we are going to use Pandas to read HTML from a string. Second, we are going to go through a couple of examples in which we scrape data from Wikipedia tables with Pandas read_html. In a previous post, about exploratory data analysis in Python, we also used Pandas to read data from HTML tables.

Import Data in Python

When starting off learning Python and Pandas, for data analysis and visualization, we usually start practicing importing data. In previous posts, we have learned that we can type in values directly in Python (e.g., creating a Pandas dataframe from a Python dictionary). However, it is, of course, more common to obtain data by importing it from available sources. Now, this most commonly done by reading data from a CSV file or Excel files. For instance, to import data from a .csv file we can use Pandas read_csv method. Here’s a quick example of how to but make sure to check the blog post about the topic for more information.

import pandas as pd

df = pd.read_csv('CSVFILE.csv')

Now, the above method is only useful when we already have data in a comfortable format such as csv or JSON (see the post about how to parse JSON files with Python and Pandas).

Most of us use Wikipedia to learn information about subjects that interest us. Additionally, these Wikipedia articles often contain HTML tables.

To get these tables in Python using pandas we could cut and paste it into a spreadsheet and then read them into Python using read_excel, for instance. Now, this task can, of course, be done with one less step: it can be automized using web scraping. Make sure to check out what web scarping is.

Prerequisites

Now, of course, this Pandas read HTML tutorial will require that we have Pandas and its dependencies installed. We can, for instance, use pip to install Python packages, such as Pandas, or we install a Python distribution (e.g., Anaconda, ActivePython). Here’s how to install Pandas with pip: pip install pandas.

Note, if there’s a message that there’s a newer version of pip available check the post about how to upgrade pip. Note, we also need lxml or BeautifulSoup4 installed and these packages can, of course, also be installed using pip:pip install lxml.

Pandas read_html Syntax

Here’s the simplest syntax of how to use Pandas read_html to scrape data from HTML tables:

pd.read_html('URL_ADDRESS_or_HTML_FILE')
pandas read_html parameters

Now that we know the simple syntax of reading an HTML table with Pandas, we can go through the read_html examples.

Pandas read_html Example 1:

In the first example, on how to use Pandas read_html method, we are going to read an HTML table from a string.

import pandas as pd

html = '''<table>
  <tr>
    <th>a</th>
    <th>b</th>
    <th>c</th>
    <th>d</th>
  </tr>
  <tr>
    <td>1</td>
    <td>2</td>
    <td>3</td>
    <td>4</td>
  </tr>
  <tr>
    <td>5</td>
    <td>6</td>
    <td>7</td>
    <td>8</td>
  </tr>
</table>'''


df = pd.read_html(html)

Now, the result we get is not a Pandas DataFrame but a Python list. That is, if we use the type() function we can see that:

type(df)
pandas read_html example

If we want to get the table, we can use the first index of the list (0):

Pandas read_html Example 2:

In the second, Pandas read_html example, we are going to scrape data from Wikipedia. In fact, we are going to get the HTML table of Pythonidae snakes (also known as Python snakes).

import pandas as pd

dfs = pd.read_html('https://en.wikipedia.org/wiki/Pythonidae')

Now, we get a list of 7 tables (len(df)). If we go to the Wikipedia page, we can see that the first table is the one to the right. In this example, however, we may be more interested in the second table.

dfs[1]
pandas read html table

Pandas read_html Example 3:

In the third example, we are going to read the HTML table from the covid-19 cases in Sweden. Here we’ll use some additional parameters o the read_html method. Specifically, we will use the match parameter. After this, we will also need to clean up the data and, finally, we will do some simple data visualizations.

Scraping Data with Pandas read_html and the match Parameter:

As can be seen, in the image above, the table has this heading: “New COVID-19 cases in Sweden by county”. Now, we can use the match parameter and use this as a string input:

dfs = pd.read_html('https://en.wikipedia.org/wiki/2020_coronavirus_pandemic_in_Sweden',
                  match='New COVID-19 cases in Sweden by county')
dfs[0].tail()
pandas read HTML table to dataframeFirst 5 columns of the dataframe

This way, we only get this table but still in a list of dataframes. Now, as can be seen in the image above we have three rows, at the bottom, that we need to remove. Thus, we are going to remove the last three rows.

Removing the Last rows using Pandas iloc

Now, we are going to remove the last 3 rows using Pandas iloc. Note, we use -3 as the second parameter (make sure you check the Pandas iloc tutorial, for more information). Finally, we also make a copy of the dataframe.

df = dfs[0].iloc[:-3, :].copy()

In the next section, we will learn how to change the MultiIndex column names to a single index.

MultiIndex to Single Index and Removing Unwanted Characters

Now, we are going to get rid of the MultiIndex columns. That is, we are going to make the 2 column index (the names) to the only column names. Here, we are going to use DataFrame.columns and DataFrame.columns,get_level_values():

df.columns = df.columns.get_level_values(1)
dataframe from HTML table

Finally, as can be seen in the “date” column, we have some notes from the WikiPedia table we have scraped using Pandas read_html. Next, we will remove them using the str.replace method together with a regular expression:

df['Date'] = df['Date'].str.replace(r"\[.*?\]","")

Changing the Index using Pandas set_index

Now, we continue by using Pandas set_index to make the date column the indexes. This is so that we can easily create a time series plot later.

df['Date'] = pd.to_datetime(df['Date'])
df.set_index('Date', inplace=True)

Now, to be able to plot this we need to fill the missing values with zeros and change the data types of these columns to numeric. Here we use the apply method, as well. Finally, we use the cumsum() method to get the added values for each new value in the columns:

df.fillna(0, inplace=True)
df = df.iloc[:,0:21].apply(pd.to_numeric)

df = df.cumsum()

Time Series Plot from HTML Table

In the final example, we take the data we scraped using Pandas read_html and create a time series plot. Now, we also import matplotlib so that we can change the location of the legend of the Pandas plot:

%matplotlib inline
import matplotlib.pyplot as plt
f = plt.figure()

plt.title('Covid cases Sweden', color='black')
df.iloc[:,0:21].plot(ax=f.gca())

plt.legend(loc='center left', bbox_to_anchor=(1.0, 0.5)))
time series plot of data scraped from HTML table using Pandas

Conclusion: How to Read HTML to a Pandas DataFrame

In this Pandas tutorial, we learned how to scrape data from HTML using Pandas read_html method. Furthermore, we used data from a Wikipedia article to create a time series plot. Finally, it would have been possible to use Pandas read_html with the parameters index_col to set the ‘Date’ column as index column.

The post How to use Pandas read_html to Scrape Data from HTML Tables appeared first on Erik Marsja.

PyBites: Productivity Mondays - a Simple yet Effective System

$
0
0

There is just too much stuff out there when it comes to being more productive. I am reading The Ultimate Sales Machine (Chet Holmes) and it offers what is probably the most concise time management system I have seen so far:

  1. Touch it once

    Don't open an email if you cannot handle it. Batch them up then do them in a miscellaneous 30 min block. Email is there for your convenience, not the other way around. This rule will avoid a lot of unnecessary distractions.

  2. Make daily lists of the six most important things you want to accomplish

    This should not be more than ~ 6 hours of work, because you have to fit it in. It's very important to become PROACTIVE about your time, rather than REACTIVE. Plan your day, or somebody else inevitably will.

  3. Plan how long each task will take

    Parkinson's law: a task will blow up in size as we alot time to it. So make sure each task has a dedicated time slot so you can actually complete it. This way you can guarantee you can cross those 6 tasks off your list and keep the momentum.

  4. Assign each task a specific time slot

    This is critical: you need to fit the important tasks into your day where emergencies might arise, meetings happen, and you want to have family, gym and reflection time as well. Add in buffers and remember: you are in control.

  5. Prioritize and focus on the most difficult projects first

    Your energy and willpower is strongest in the morning so tackle the most important (and often most difficult) tasks early in the morning. As Brian Tracy says: eat that (ugly) frog first thing and you win the day.

  6. Whenever you handle a new piece of paper, ask yourself, “Will it hurt me to throw this away?”

    No need to keep all those emails around, keep notes in Dropbox/Evernote of the essentials. Live a lean/ decluttered life.


I hope this helps controlling your time more effectively.

What one thing was critical in making you more productive this week?

-- Bob

With so many avenues to pursue in Python it can be tough to know what to do. If you're looking for some direction or want to take your Python code and career to the next level, schedule a call with us now. We can help you!


Podcast.__init__: A Flexible Open Source ERP Framework To Run Your Business

$
0
0
Running a successful business requires some method of organizing the information about all of the processes and activity that take place. Tryton is an open source, modular ERP framework that is built for the flexibility needed to fit your organization, rather than requiring you to model your workflows to match the software. In this episode core developers Nicolas Évrard and Cédric Krier are joined by avid user Jonathan Levy to discuss the history of the project, how it is being used, and the myriad ways that you can adapt it to suit your needs. If you are struggling to keep a consistent view of your business and ensure that all of the necessary workflows are being observed then listen now and give Tryton a try.

Summary

Running a successful business requires some method of organizing the information about all of the processes and activity that take place. Tryton is an open source, modular ERP framework that is built for the flexibility needed to fit your organization, rather than requiring you to model your workflows to match the software. In this episode core developers Nicolas Évrard and Cédric Krier are joined by avid user Jonathan Levy to discuss the history of the project, how it is being used, and the myriad ways that you can adapt it to suit your needs. If you are struggling to keep a consistent view of your business and ensure that all of the necessary workflows are being observed then listen now and give Tryton a try.

Announcements

  • Hello and welcome to Podcast.__init__, the podcast about Python and the people who make it great.
  • When you’re ready to launch your next app or want to try a project you hear about on the show, you’ll need somewhere to deploy it, so take a look at our friends over at Linode. With 200 Gbit/s private networking, node balancers, a 40 Gbit/s public network, fast object storage, and a brand new managed Kubernetes platform, all controlled by a convenient API you’ve got everything you need to scale up. And for your tasks that need fast computation, such as training machine learning models, they’ve got dedicated CPU and GPU instances. Go to pythonpodcast.com/linode to get a $20 credit and launch a new server in under a minute. And don’t forget to thank them for their continued support of this show!
  • You listen to this show to learn and stay up to date with the ways that Python is being used, including the latest in machine learning and data analysis. For even more opportunities to meet, listen, and learn from your peers you don’t want to miss out on this year’s conference season. We have partnered with organizations such as O’Reilly Media, Corinium Global Intelligence, ODSC, and Data Council. Go to pythonpodcast.com/conferences to learn more about these and other events, and take advantage of our partner discounts to save money when you register today.
  • Your host as usual is Tobias Macey and today I’m interviewing Nicolas Évrard, Cédric Krier, and Jonathan Levy about Tryton

Interview

  • Introductions
  • How did you get introduced to Python?
  • Can you start by describing what Tryton is and how it got started?
  • What kinds of businesses is Tryton most suited to?
    • What kinds of businesses is Tryton not a good fit for?
  • Within a business, who are the primary users of Tryton?
  • Can you talk through a typical workflow for interacting with Tryton?
  • What are some of the most complex or challenging aspects of modeling a business while maintaining a high degree of customizability?
  • Can you describe how Tryton is architected and how its design has evolved since it was first started?
    • If you were to start over today, what would you do differently?
  • There are a number of plugins for Tryton. What kinds of functionality can be customized using the available interfaces?
    • What is the process for building a custom module for Tryton?
  • How do you manage sustainability of the Tryton project?
  • Given the criticality of the Tryton platform, how do you approach ongoing stability and security of the project?
  • What is involved in deploying and maintaining an installation of Tryton?
  • What are some of the most interesting, innovative, or unexpected ways that you have seen Tryton used?
  • What is in store for the future of Tryton?

Keep In Touch

Picks

Links

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

BreadcrumbsCollector: mypy: how to use it in my project? Part 2: automatically annotate code

$
0
0

Even after successful integration of mypy with an existing project (see mypy: how to use it in my project part 1), there are tons of code that does not have type annotations. Adding them manually is an unimaginable amount of work. We may do it gradually (as suggested in part 1) or use tools to help us.

Using PyCharm to get type annotations

This recipe requires you to use PyCharm and have tests written for your code. Assuming that’s your code:

async def websocket_handler(request):
    ws = web.WebSocketResponse()
    await ws.prepare(request)

    async for msg in ws:
        if msg.type == WSMsgType.TEXT:
            data = msg.json()
            await ws.send_json(
                {
                    'message': data['message'],
                    'from': data['from'],
                    'timestamp': time.time()
                }
            )
        elif msg.type == WSMsgType.ERROR:
            logger.error('ws connection closed with exception %s' % ws.exception())

    return ws

…and there goes a test for it:

async def test_receives_sent_message(aiohttp_client):
    client = await aiohttp_client(create_app)
    connection = await client.ws_connect('/ws?nickname=JohnDoe')

    message = 'Hello, world!'
    example_payload = {'message': message, 'from': 'JohnDoe', 'timestamp': 0}
    await connection.send_json(example_payload)
    response = await connection.receive_json()

    assert response['message'] == message

This is a WebSocket view for chat application. It comes from my asyncio-tutorial from 2017 edition of PyconPL. This proto-chat just sends back everything one has sent to it.

Now, to get type annotations you have to first enable collecting run-time types information. In order to do so, open Settings, go to Build, Execution, Deployment and open Python Debugger page. There, turn on the option labelled as Collect run-time types information for code insight.

Then, navigate to your tests and run them under the debugger. In my case, I have only a single test, so I will simply run it using UI:

The next step is to go back to your code, select a code element (e.g. view function) by single-clicking it and press a key shortcut (Alt + Enter on Linux). Then, click first option Add type hints for function ‘websocket_handler’.

Voilà, type annotations appear:

async def websocket_handler(request: aiohttp.web_request.Request) -> Union[_asyncio.Future, aiohttp.web_ws.WebSocketResponse]:
    ...

In case you forgot to run your tests with debugger or run-time type information has not been collected, PyCharm would just add “object” for both argument and return type. If this happens to you, recheck settings and remember to run tests from PyCharm using debug!

It is not over yet – you still have to clean this thing up a bit by removing the excessive information and adding missing imports or fixing paths. In this particular example, the first element of Union is not particularly helpful, so we remove it and just leave WebSocketResponse there. As for paths, both Request and WebSocketResponse are also imported to aiohttp.web which we imported in the module, so we can just change annotations and shorten the whole thing:

from aiohttp import (
    web,
    WSMsgType,
)


async def websocket_handler(request: web.Request) -> web.WebSocketResponse:
    ...

…and we are now good to go 🙂 Don’t forget to run mypy afterwards and see if it finds any issues!

Why this approach will never be as good as manual annotation?

Although having any type hints (pun intended) seems to make a great change, you have to aware of caveats of such generation. Automatic tools are doing their best, but won’t be able to annotate code with more generic information. Consider the following example:

def get_top_3(iterable):
    sorted_items = sorted(iterable, reverse=True)
    return sorted_items[:3]


def test_foo_dict():
    iterable = {1: 'Jack', 2: 'Janine', 0: 'John', 3: 'Mark'}
    assert get_top_3(iterable) == [3, 2, 1]


def test_foo_tuple():
    iterable = 'Jack', 'Janine', 'John', 'Mark', 'Peter'
    assert get_top_3(iterable) == ['Peter', 'Mark', 'John']


def test_foo_list():
    iterable = list(range(10))
    assert get_top_3(iterable) == [9, 8, 7]

As you can see, get_top_3 function can really work with any iterable object. But when we run these tests under the debugger and try to generate annotations, we get:

from typing import Dict, List, Tuple, Union

def get_top_3(iterable: Union[Dict[int, str], Tuple[str, str, str, str, str], List[int]]) -> Union[List[int], List[str]]:
    sorted_items = sorted(iterable, reverse=True)
    return sorted_items[:3]

That looks terrible, but should not really surprise us. PyCharm did its best by combining types from all possible combinations but the result is very, very specific. The funniest part is how Tuple[str, str, str, str] appeared. It means that this particular annotation tells us the function will accept a tuple of strings that has exactly 4 elements, but definitely not if a tuple has 2 or 5 elements. Also, pay attention that return type has been generated in a wrong way – mypy 0.770 complains about it:

tests.py:22: error: Incompatible return value type (got "List[object]", expected "Union[List[int], List[str]]")

Using Generics

However, using our Python superpower we know that this function can accept anything that supports iteration over its elements (defines __iter__ function) and it has items that are comparable so we can sort it. To know which generic should be used here, we go to typing module documentation.

The one we are looking for is Iterable. For return type it is simpler – it is always a list:

def get_top_3(iterable: Iterable) -> List:
    sorted_items = sorted(iterable, reverse=True)
    return sorted_items[:3]

Now, we are not done yet. Generics can be parametrized. It’s nice to know that we will get a list, but we do not know what will be types of elements. The same goes for Iterable. This generic alone gives no clue if this function will work with a list of dictionaries or not (spoiler: it will crash miserably, because dictionaries cannot be compared for sorting purposes). In order to protect ourselves from it, we need to parametrize our generics. Let’s break this down. We know that elements of resultant list will have the same type as elements we iterate. For that purpose, there is a generic typing.TypeVar:

T = TypeVar('T')


def get_top_3(iterable: Iterable[T]) -> List[T]:
    sorted_items = sorted(iterable, reverse=True)
    return sorted_items[:3]

This is already nice because now our IDE or mypy is able to tell what’s the type of each element in response. It is done automatically. E.g. if we pass an iterable of strings, it knows we return a list of strings. If we passed a tuple of integers, we would expect a list of integers back.

This is a huge help for mypy and other static code analysis tools.

Now, the final problem is that haven’t conveyed requirement about elements types – they have to be comparable with each other. Unfortunately, at the moment of writing this article, there is nothing included in the stdlib that could be used to annotate comparability. I also was unable to find a reliable workaround, so that area remains uncovered. Hopefully, I will update the article in the future with relevant information 🙂

Other tools worth checking out

Summary

Although the automatic generation of Python type hints is not ideal, it can still spare you some mundane work. Stay tuned for part 3, where we will explore kick-ass tools that leverage type hints!

The post mypy: how to use it in my project? Part 2: automatically annotate code appeared first on Breadcrumbs Collector.

James Bennett: Against service layers in Django

$
0
0

This post now has a followup.

Recently I’ve seen posts and questions pop up in a few places about a sort of “enterprise” Django style guide that’s been getting attention. There are a number of things I disagree with in that guide, but the big one, and the one people have mostly been asking about, is the recommendation to add a “service layer” to Django applications. The short version of my opinion on this …

Read full entry

James Bennett: More on service layers in Django

$
0
0

Well, that provoked some discussion.

While there were plenty of people who agreed with the general idea of that post, there were also quite a few objections. And most of those seem to fall into two main categories: people who want some type of additional layer (and may or may not call it a “service”) as a way of managing cross-cutting complexity, and people who want it as an isolating abstraction for testing.

There’s also a third …

Read full entry

"Coder's Cat": How to Shuffle a List in Python

$
0
0

Shuffle a List with Random

random is a Python module that implements pseudo-random number generators. random.shuffle can shuffle a list in-place.

random.shuffle(x[, random])
Shuffle the sequence x in place.

The optional argument random is a 0-argument function returning a random float in [0.0, 1.0); by default, this is the function random().

Let’s run a simple usage example. From the output we can see the list is modified after shuffling, this is called in-place strategy:

import random
numbers = [71, 1, 21, 22, 35, 41, 49, 56, 63, 70]
print ("Original: ",  numbers)
> ('Original: ', [71, 1, 21, 22, 35, 41, 49, 56, 63, 70])

random.shuffle(numbers) #shuffle method
print ("Shuffled: ",  numbers)
> ('Shuffled: ', [49, 22, 63, 70, 56, 21, 1, 71, 41, 35])

We can also use random.shuffle() to shuffle a list with strings.

a = ["hello", "coder", "cat"]
random.shuffle(a)
print(a)
> ['coder', 'hello', 'cat']

Shuffle a list with not-in-place

If we don’t want to modify the original list, we can use another function called random.sample, it will return a new list and keep the original list un-touched.

This is called not-in-place strategy:

import random
numbers = [71, 1, 21, 22, 35, 41, 49, 56, 63, 70]
new_numbers = random.sample(numbers, len(numbers))
print ("new_numbers: ",  new_numbers)
> ('new_numbers: ', [56, 35, 49, 41, 71, 70, 22, 63, 1, 21])

Implement it by yourself

Challenge:

Implement a Python function which will shuffle a list, return a new list.

If this is an interview question, can you finish it bug-free in 15 minutes?

Have a try now 🙂

A simple algorithm for shuffling array or list is Fisher-Yates:

from copy import deepcopy
from random import randint

def shuffle(lst):
    tmp = deepcopy(lst)
    m = len(tmp)
    while(m):
        m -= 1
        i = randint(0, m)
        tmp[m], tmp[i] = tmp[i], tmp[m]
    return tmp

foo = [1,2,3]
shuffle(foo) # [2,3,1] , foo = [1,2,3]

The post How to Shuffle a List in Python appeared first on CodersCat.

Twisted Matrix Labs: Twisted Drops Python 2.7 Support

$
0
0
With the open-source Python community at large dropping Python 2.7 support in their projects, Twisted has decided to do the same. Twisted 20.3.0, the most recently released version, is the final release to offer Python 2.7 support.

Despite the break, the compatibility policy still applies. This means that if your code works with Twisted 20.3 on Python 2.7 and 3.5+, that updating your Twisted on Python 3 up to a theoretical 21.3 would not require changes that would make Python 2.7 + Twisted 20.3 stop working, despite a theoretical Twisted 21.3 not supporting 2.7. (This is, of course, in an ideal situation -- regressions and changes that are excepted from the policy such as security fixes do occur. Testing your applications on Twisted prereleases can help catch places where this happens, so, please do!)

- Amber (HawkOwl)

Real Python: The Python math Module: Everything You Need to Know

$
0
0

In this article, you’ll learn all about Python’s math module. Mathematical calculations are an essential part of most Python development. Whether you’re working on a scientific project, a financial application, or any other type of programming endeavor, you just can’t escape the need for math.

For straightforward mathematical calculations in Python, you can use the built-in mathematical operators, such as addition (+), subtraction (-), division (/), and multiplication (*). But more advanced operations, such as exponential, logarithmic, trigonometric, or power functions, are not built in. Does that mean you need to implement all of these functions from scratch?

Fortunately, no. Python provides a module specifically designed for higher-level mathematical operations: the math module.

By the end of this article, you’ll learn:

  • What the Python math module is
  • How to use math module functions to solve real-life problems
  • What the constants of the math module are, including pi, tau, and Euler’s number
  • What the differences between built-in functions and math functions are
  • What the differences between math, cmath, and NumPy are

A background in mathematics will be helpful here, but don’t worry if math isn’t your strong suit. This article will explain the basics of everything you need to know.

So let’s get started!

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

Getting to Know the Python math Module

The Python math module is an important feature designed to deal with mathematical operations. It comes packaged with the standard Python release and has been there from the beginning. Most of the math module’s functions are thin wrappers around the C platform’s mathematical functions. Since its underlying functions are written in CPython, the math module is efficient and conforms to the C standard.

The Python math module offers you the ability to perform common and useful mathematical calculations within your application. Here are a few practical uses for the math module:

  • Calculating combinations and permutations using factorials
  • Calculating the height of a pole using trigonometric functions
  • Calculating radioactive decay using the exponential function
  • Calculating the curve of a suspension bridge using hyperbolic functions
  • Solving quadratic equations
  • Simulating periodic functions, such as sound and light waves, using trigonometric functions

Since the math module comes packaged with the Python release, you don’t have to install it separately. Using it is just a matter of importing the module:

>>>
>>> importmath

You can import the Python math module using the above command. After importing, you can use it straightaway.

Constants of the math Module

The Python math module offers a variety of predefined constants. Having access to these constants provides several advantages. For one, you don’t have to manually hardcode them into your application, which saves you a lot of time. Plus, they provide consistency throughout your code. The module includes several famous mathematical constants and important values:

  • Pi
  • Tau
  • Euler’s number
  • Infinity
  • Not a number (NaN)

In this section, you’ll learn about the constants and how to use them in your Python code.

Pi

Pi (π) is the ratio of a circle’s circumference (c) to its diameter (d):

π = c/d

This ratio is always the same for any circle.

Pi is an irrational number, which means it can’t be expressed as a simple fraction. Therefore, pi has an infinite number of decimal places, but it can be approximated as 22/7, or 3.141.

Interesting Fact: Pi is the most recognized and well-known mathematical constant in the world. It has its own celebration date, called Pi Day, which falls on March 14th (3/14).

You can access pi as follows:

>>>
>>> math.pi3.141592653589793

As you can see, the pi value is given to fifteen decimal places in Python. The number of digits provided depends on the underlying C compiler. Python prints the first fifteen digits by default, and math.pi always returns a float value.

So what are some of the ways that pi can be useful to you? You can calculate the circumference of a circle using 2πr, where r is the radius of the circle:

>>>
>>> r=3>>> circumference=2*math.pi*r>>> f"Circumference of a Circle = 2 * {math.pi:.4} * {r} = {circumference:.4}"'Circumference of a Circle = 2 * 3.142 * 3 = 18.85'

You can use math.pi to calculate the circumference of a circle. You can also calculate the area of a circle using the formula πr² as follows:

>>>
>>> r=5>>> area=math.pi*r*r>>> f"Area of a Circle = {math.pi:.4} * {r} * {r} = {area:.4}"'Area of a Circle = 3.142 * 5 * 5 = 78.54'

You can use math.pi to calculate the area and the circumference of a circle. When you are doing mathematical calculations with Python and you come across a formula that uses π, it’s a best practice to use the pi value given by the math module instead of hardcoding the value.

Tau

Tau (τ) is the ratio of a circle’s circumference to its radius. This constant is equal to 2π, or roughly 6.28. Like pi, tau is an irrational number because it’s just pi times two.

Many mathematical expressions use 2π, and using tau instead can help simplify your equations. For example, instead of calculating the circumference of a circle with 2πr, we can substitute tau and use the simpler equation τr.

The use of tau as the circle constant, however, is still under debate. You have the freedom to use either 2π or τ as necessary.

You can use tau as below:

>>>
>>> math.tau6.283185307179586

Like math.pi, math.tau returns fifteen digits and is a float value. You can use tau to calculate the circumference of a circle with τr, where r is the radius, as follows:

>>>
>>> r=3>>> circumference=math.tau*r>>> f"Circumference of a Circle = {math.tau:.4} * {r} = {circumference:.4}"'Circumference of a Circle = 6.283 * 3 = 18.85'

You can use math.tau in place of 2 * math.pi to tidy up equations that include the expression 2π.

Euler’s Number

Euler’s number (e) is a constant that is the base of the natural logarithm, a mathematical function that is commonly used to calculate rates of growth or decay. As with pi and tau, Euler’s number is an irrational number with infinite decimal places. The value of e is often approximated as 2.718.

Euler’s number is an important constant because it has many practical uses, such as calculating population growth over time or determining rates of radioactive decay. You can access Euler’s number from the math module as follows:

>>>
>>> math.e2.718281828459045

As with math.pi and math.tau, the value of math.e is given to fifteen decimal places and is returned as a float value.

Infinity

Infinity can’t be defined by a number. Rather, it’s a mathematical concept representing something that is never-ending or boundless. Infinity can go in either direction, positive or negative.

You can use infinity in algorithms when you want to compare a given value to an absolute maximum or minimum value. The values of positive and negative infinity in Python are as follows:

>>>
>>> f"Positive Infinity = {math.inf}"'Positive Infinity = inf'>>> f"Negative Infinity = {-math.inf}"'Negative Infinity = -inf'

Infinity is not a numerical value. Instead, it’s defined as math.inf. Python introduced this constant in version 3.5 as an equivalent to float("inf"):

>>>
>>> float("inf")==math.infTrue

Both float("inf") and math.inf represent the concept of infinity, making math.inf greater than any numerical value:

>>>
>>> x=1e308>>> math.inf>xTrue

In the above code, math.inf is greater than the value of x, 10308 (the maximum size of a floating-point number), which is a double precision number.

Similarly, -math.inf is smaller than any value:

>>>
>>> y=-1e308>>> y>-math.infTrue

Negative infinity is smaller than the value of y, which is -10308. No number can be greater than infinity or smaller than negative infinity. That’s why mathematical operations with math.inf don’t change the value of infinity:

>>>
>>> math.inf+1e308inf>>> math.inf/1e308inf

As you can see, neither addition nor division changes the value of math.inf.

Not a Number (NaN)

Not a number, or NaN, isn’t really a mathematical concept. It originated in the computer science field as a reference to values that are not numeric. A NaN value can be due to invalid inputs, or it can indicate that a variable that should be numerical has been corrupted by text characters or symbols.

It’s always a best practice to check if a value is NaN. If it is, then it could lead to invalid values in your program. Python introduced the NaN constant in version 3.5.

You can observe the value of math.nan below:

>>>
>>> math.nannan

NaN is not a numerical value. You can see that the value of math.nan is nan, the same value as float("nan").

Arithmetic Functions

Number theory is a branch of pure mathematics, which is the study of natural numbers. Number theory usually deals with positive whole numbers or integers.

The Python math module provides functions that are useful in number theory as well as in representation theory, a related field. These functions allow you to calculate a range of important values, including the following:

  • The factorials of a number
  • The greatest common divisor of two numbers
  • The sum of iterables

Find Factorials With Python factorial()

You may have seen mathematical expressions like 7! or 4! before. The exclamation marks don’t mean that the numbers are excited. Rather, “!” is the factorial symbol. Factorials are used in finding permutations or combinations. You can determine the factorial of a number by multiplying all whole numbers from the chosen number down to 1.

The following table shows the factorial values for 4, 6, and 7:

SymbolIn WordsExpressionResult
4!Four factorial4 x 3 x 2 x 124
6!Six factorial6 x 5 x 4 x 3 x 2 x 1720
7!Seven factorial7 x 6 x 5 x 4 x 3 x 2 x 15040

You can see from the table that 4!, or four factorial, gives the value 24 by multiplying the range of whole numbers from 4 to 1. Similarly, 6! and 7! give the values 720 and 5040, respectively.

You can implement a factorial function in Python using one of several tools:

  1. for loops
  2. Recursive functions
  3. math.factorial()

First you are going to look at a factorial implementation using a for loop. This is a relatively straightforward approach:

deffact_loop(num):ifnum<0:return0ifnum==0:return1factorial=1foriinrange(1,num+1):factorial=factorial*ireturnfactorial

You can also use a recursive function to find the factorial. This is more complicated but also more elegant than using a for loop. You can implement the recursive function as follows:

deffact_recursion(num):ifnum<0:return0ifnum==0:return1returnnum*fact_recursion(num-1)

Note: There is a limit to the recursion depth in Python, but that subject is outside the scope of this article.

The following example illustrates how you can use the for loop and recursive functions:

>>>
>>> fact_loop(7)5040>>> fact_recursion(7)5040

Even though their implementations are different, their return values are the same.

However, implementing functions of your own just to get the factorial of a number is time consuming and inefficient. A better method is to use math.factorial(). Here’s how you can find the factorial of a number using math.factorial():

>>>
>>> math.factorial(7)5040

This approach returns the desired output with a minimal amount of code.

factorial() accepts only positive integer values. If you try to input a negative value, then you will get a ValueError:

>>>
>>> math.factorial(-5)Traceback (most recent call last):
  File "<stdin>", line 1, in <module>ValueError: factorial() not defined for negative values

Inputting a negative value will result in a ValueError reading factorial() not defined for negative values.

factorial() doesn’t accept decimal numbers, either. It will give you a ValueError:

>>>
>>> math.factorial(4.3)Traceback (most recent call last):
  File "<stdin>", line 1, in <module>ValueError: factorial() only accepts integral values

Inputting a decimal value results in a ValueError reading factorial() only accepts integral values.

You can compare the execution times for each of the factorial methods using timeit():

>>>
>>> importtimeit>>> timeit.timeit("fact_loop(10)",globals=globals())1.063997201999996>>> timeit.timeit("fact_recursion(10)",globals=globals())1.815312818999928>>> timeit.timeit("math.factorial(10)",setup="import math")0.10671788000001925

The sample above illustrates the results of timeit() for each of the three factorial methods.

timeit() executes one million loops each time it is run. The following table compares the execution times of the three factorial methods:

TypeExecution Time
With loops1.0640 s
With recursion1.8153 s
With factorial()0.1067 s

As you can see from the execution times, factorial() is faster than the other methods. That’s because of its underlying C implementation. The recursion-based method is the slowest out of the three. Although you might get different timings depending on your CPU, the order of the functions should be the same.

Not only is factorial() faster than the other methods, but it’s also more stable. When you implement your own function, you have to explicitly code for disaster cases such as handling negative or decimal numbers. One mistake in the implementation could lead to bugs. But when using factorial(), you don’t have to worry about disaster cases because the function handles them all. Therefore, it’s a best practice to use factorial() whenever possible.

Find the Ceiling Value With ceil()

math.ceil() will return the smallest integer value that is greater than or equal to the given number. If the number is a positive or negative decimal, then the function will return the next integer value greater than the given value.

For example, an input of 5.43 will return the value 6, and an input of -12.43 will return the value -12. math.ceil() can take positive or negative real numbers as input values and will always return an integer value.

When you input an integer value to ceil(), it will return the same number:

>>>
>>> math.ceil(6)6>>> math.ceil(-11)-11

math.ceil() always returns the same value when an integer is given as input. To see the true nature of ceil(), you have to input decimal values:

>>>
>>> math.ceil(4.23)5>>> math.ceil(-11.453)-11

When the value is positive (4.23), the function returns the next integer greater than the value (5). When the value is negative (-11.453), the function likewise returns the next integer greater than the value (-11).

The function will return a TypeError if you input a value that is not a number:

>>>
>>> math.ceil("x")Traceback (most recent call last):
  File "<stdin>", line 1, in <module>TypeError: must be real number, not str

You must input a number to the function. If you try to input any other value, then you will get a TypeError.

Find the Floor Value With floor()

floor() will return the closest integer value that is less than or equal to the given number. This function behaves opposite to ceil(). For example, an input of 8.72 will return 8, and an input of -12.34 will return -13. floor() can take either positive or negative numbers as input and will return an integer value.

If you input an integer value, then the function will return the same value:

>>>
>>> math.floor(4)4>>> math.floor(-17)-17

As with ceil(), when the input for floor() is an integer, the result will be the same as the input number. The output only differs from the input when you input decimal values:

>>>
>>> math.floor(5.532)5>>> math.floor(-6.432)-7

When you input a positive decimal value (5.532), it will return the closest integer that is less than the input number (5). If you input a negative number (-6.432), then it will return the next lowest integer value (-7).

If you try to input a value that is not a number, then the function will return a TypeError:

>>>
>>> math.floor("x")Traceback (most recent call last):
  File "<stdin>", line 1, in <module>TypeError: must be real number, not str

You can’t give non-number values as input to ceil(). Doing so will result in a TypeError.

Truncate Numbers With trunc()

When you get a number with a decimal point, you might want to keep only the integer part and eliminate the decimal part. The math module has a function called trunc() which lets you do just that.

Dropping the decimal value is a type of rounding. With trunc(), negative numbers are always rounded upward toward zero and positive numbers are always rounded downward toward zero.

Here is how the trunc() function rounds off positive or negative numbers:

>>>
>>> math.trunc(12.32)12>>> math.trunc(-43.24)-43

As you can see, 12.32 is rounded downwards towards 0, which gives the result 12. In the same way, -43.24 is rounded upwards towards 0, which gives the value -43. trunc() always rounds towards zero regardless of whether the number is positive or negative.

When dealing with positive numbers, trunc() behaves the same as floor():

>>>
>>> math.trunc(12.32)==math.floor(12.32)True

trunc() behaves the same as floor() for positive numbers. As you can see, the return value of both functions is the same.

When dealing with negative numbers, trunc() behaves the same as ceil():

>>>
>>> math.trunc(-43.24)==math.ceil(-43.24)True

When the number is negative, floor() behaves the same as ceil(). The return values of both functions are the same.

Find the Closeness of Numbers With Python isclose()

In certain situations—particularly in the data science field—you may need to determine whether two numbers are close to each other. But to do so, you first need to answer an important question: How close is close? In other words, what is the definition of close?

Well, Merriam-Webster will tell you that close means “near in time, space, effect, or degree.” Not very helpful, is it?

For example, take the following set of numbers: 2.32, 2.33, and 2.331. When you measure closeness by two decimal points, 2.32 and 2.33 are close. But in reality, 2.33 and 2.331 are closer. Closeness, therefore, is a relative concept. You can’t determine closeness without some kind of threshold.

Fortunately, the math module provides a function called isclose() that lets you set your own threshold, or tolerance, for closeness. It returns True if two numbers are within your established tolerance for closeness and otherwise returns False.

Let’s check out how to compare two numbers using the default tolerances:

  • Relative tolerance, or rel_tol, is the maximum difference for being considered “close” relative to the magnitude of the input values. This is the percentage of tolerance. The default value is 1e-09 or 0.000000001.
  • Absolute tolerance, or abs_tol, is the maximum difference for being considered “close” regardless of the magnitude of the input values. The default value is 0.0.

isclose() will return True when the following condition is satisfied:

abs(a-b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol).

isclose uses the above expression to determine the closeness of two numbers. You can substitute your own values and observe whether any two numbers are close.

In the following case, 6 and 7 aren’t close:

>>>
>>> math.isclose(6,7)False

The numbers 6 and 7 aren’t considered close because the relative tolerance is set for nine decimal places. But if you input 6.999999999 and 7 under the same tolerance, then they are considered close:

>>>
>>> math.isclose(6.999999999,7)True

You can see that the value 6.999999999 is within nine decimal places of 7. Therefore, based on the default relative tolerance, 6.999999999 and 7 are considered close.

You can adjust the relative tolerance however you want depending on your need. If you set rel_tol to 0.2, then 6 and 7 are considered close:

>>>
>>> math.isclose(6,7,rel_tol=0.2)True

You can observe that 6 and 7 are close now. This is because they are within 20% of each other.

As with rel_tol, you can adjust the abs_tol value according to your needs. To be considered close, the difference between the input values must be less than or equal to the absolute tolerance value. You can set the abs_tol as follows:

>>>
>>> math.isclose(6,7,abs_tol=1.0)True>>> math.isclose(6,7,abs_tol=0.2)False

When you set the absolute tolerance to 1, the numbers 6 and 7 are close because the difference between them is equal to the absolute tolerance. However, in the second case, the difference between 6 and 7 is not less than or equal to the established absolute tolerance of 0.2.

You can use the abs_tol for very small values:

>>>
>>> math.isclose(1,1.0000001,abs_tol=1e-08)False>>> math.isclose(1,1.00000001,abs_tol=1e-08)True

As you can see, you can determine the closeness of very small numbers with isclose. A few special cases regarding closeness can be illustrated using nan and inf values:

>>>
>>> math.isclose(math.nan,1e308)False>>> math.isclose(math.nan,math.nan)False>>> math.isclose(math.inf,1e308)False>>> math.isclose(math.inf,math.inf)True

You can see from the above examples that nan is not close to any value, not even to itself. On the other hand, inf is not close to any numerical values, not even to very large ones, but it is close to itself.

Power Functions

The power function takes any number x as input, raises x to some power n, and returns xn as output. Python’s math module provides several power-related functions. In this section, you’ll learn about power functions, exponential functions, and square root functions.

Calculate the Power of a Number With pow()

Power functions have the following formula where the variable x is the base, the variable n is the power, and a can be any constant:

Power FunctionPower Function

In the formula above, the value of the base x is raised to the power of n.

You can use math.pow() to get the power of a number. There is a built-in function, pow(), that is different from math.pow(). You will learn the difference later in this section.

math.pow() takes two parameters as follows:

>>>
>>> math.pow(2,5)32.0>>> math.pow(5,2.4)47.59134846789696

The first argument is the base value and the second argument is the power value. You can give an integer or a decimal value as input and the function always returns a float value. There are some special cases defined in math.pow().

When the base 1 is raised to the power of any number n, it gives the result 1.0:

>>>
>>> math.pow(1.0,3)1.0

When you raise base value 1 to any power value, you will always get 1.0 as the result. Likewise, any base number raised to the power of 0 gives the result 1.0:

>>>
>>> math.pow(4,0.0)1.0>>> math.pow(-4,0.0)1.0

As you can see, any number raised to the power of 0 will give 1.0 as the result. You can see that result even if the base is nan:

>>>
>>> math.pow(math.nan,0.0)1.0

Zero raised to the power of any positive number will give 0.0 as the result:

>>>
>>> math.pow(0.0,2)0.0>>> math.pow(0.0,2.3)0.0

But if you try to raise 0.0 to a negative power, then the result will be a ValueError:

>>>
>>> math.pow(0.0,-2)Traceback (most recent call last):
  File "<stdin>", line 1, in <module>ValueError: math domain error

The ValueError only occurs when the base is 0. If the base is any other number except 0, then the function will return a valid power value.

Apart from math.pow(), there are two built-in ways of finding the power of a number in Python:

  1. x ** y
  2. pow()

The first option is straightforward. You may have used it a time or two already. The return type of the value is determined by the inputs:

>>>
>>> 3**29>>> 2**3.39.849155306759329

When you use integers, you get an integer value. When you use decimal values, the return type changes to a decimal value.

The second option is a versatile built-in function. You don’t have to use any imports to use it. The built-in pow() method has three parameters:

  1. The base number
  2. The power number
  3. The modulus number

The first two parameters are mandatory, whereas the third parameter is optional. You can input integers or decimal numbers and the function will return the appropriate result based on the input:

>>>
>>> pow(3,2)9>>> pow(2,3.3)9.849155306759329

The built-in pow() has two required arguments that work the same as the base and power in the x ** y syntax. The pow() method also has a third parameter that is optional: modulus. This parameter is often used in cryptography. Built-in pow() with the optional modulus parameter is equivalent to the equation (x ** y) % z. The Python syntax looks like this:

>>>
>>> pow(32,6,5)4>>> (32**6)%5==pow(32,6,5)True

pow() raises the base (32) to the power (6), and then the result value is modulo divided by the modulus number (5). In this case, the result is 4. You can substitute your own values and see that both pow() and the given equation provide the same results.

Even though all three methods of calculating power do the same thing, there are some implementation differences between them. The execution times for each method are as follows:

>>>
>>> timeit.timeit("10 ** 308")1.0078728999942541>>> timeit.timeit("pow(10, 308)")1.047615700008464>>> timeit.timeit("math.pow(10, 308)",setup="import math")0.1837239999877056

The following table compares the execution times of the three methods as measured by timeit():

TypeExecution Time
x ** y1.0079 s
pow(x, y)1.0476 s
math.pow(x, y)0.1837 s

You can observe from the table that math.pow() is faster than the other methods and built-in pow() is the slowest.

The reason behind the efficiency of math.pow() is the way that it’s implemented. It relies on the underlying C language. On the other hand, pow() and x ** y use the input object’s own implementation of the ** operator. However, math.pow() can’t handle complex numbers (which will be explained in a later section), whereas pow() and ** can.

Find the Natural Exponent With exp()

You learned about power functions in the previous section. With exponential functions, things are a bit different. Instead of the base being the variable, power becomes the variable. It looks something like this:

General Exponential FunctionGeneral Exponential Function

Here a can be any constant, and x, which is the power value, becomes the variable.

So what’s so special about exponential functions? The value of the function grows rapidly as the x value increases. If the base is greater than 1, then the function continuously increases in value as x increases. A special property of exponential functions is that the slope of the function also continuously increases as x increases.

You learned about the Euler’s number in a previous section. It is the base of the natural logarithm. It also plays a role with the exponential function. When Euler’s number is incorporated into the exponential function, it becomes the natural exponential function:

Natural Exponential FunctionNatural Exponential Function

This function is used in many real-life situations. You may have heard of the term exponential growth, which is often used in relation to human population growth or rates of radioactive decay. Both of these can be calculated using the natural exponential function.

The Python math module provides a function, exp(), that lets you calculate the natural exponent of a number. You can find the value as follows:

>>>
>>> math.exp(21)1318815734.4832146>>> math.exp(-1.2)0.30119421191220214

The input number can be positive or negative, and the function always returns a float value. If the number is not a numerical value, then the method will return a TypeError:

>>>
>>> math.exp("x")Traceback (most recent call last):
  File "<stdin>", line 1, in <module>TypeError: must be real number, not str

As you can see, if the input is a string value, then the function returns a TypeError reading must be real number, not str.

You can also calculate the exponent using the math.e ** x expression or by using pow(math.e, x). The execution times of these three methods are as follows:

>>>
>>> timeit.timeit("math.e ** 308",setup="import math")0.17853009998701513>>> timeit.timeit("pow(math.e, 308)",setup="import math")0.21040189999621361>>> timeit.timeit("math.exp(308)",setup="import math")0.125878200007719

The following table compares the execution times of the above methods as measured by timeit():

TypeExecution Time
e ** x0.1785 s
pow(e, x)0.2104 s
math.exp(x)0.1259 s

You can see that math.exp() is faster than the other methods and pow(e, x) is the slowest. This is the expected behavior because of the underlying C implementation of the math module.

It’s also worth noting that e ** x and pow(e, x) return the same values, but exp() returns a slightly different value. This is due to implementation differences. Python documentation notes that exp() is more accurate than the other two methods.

Practical Example With exp()

Radioactive decay happens when an unstable atom loses energy by emitting ionizing radiation. The rate of radioactive decay is measured using half-life, which is the time it takes for half the amount of the parent nucleus to decay. You can calculate the decay process using the following formula:

Radioactive Decay Equation of a Radioactive ElementRadioactive Decay Equation

You can use the above formula to calculate the remaining quantity of a radioactive element after a certain number of years. The variables of the given formula are as follows:

  • N(0) is the initial quantity of the substance.
  • N(t) is the quantity that still remains and has not yet decayed after a time (t).
  • T is the half-life of the decaying quantity.
  • e is Euler’s number.

Scientific research has identified the half-lives of all radioactive elements. You can substitute values to the equation to calculate the remaining quantity of any radioactive substance. Let’s try that now.

The radioisotope strontium-90 has a half-life of 38.1 years. A sample contains 100 mg of Sr-90. You can calculate the remaining milligrams of Sr-90 after 100 years:

>>>
>>> half_life=38.1>>> initial=100>>> time=100>>> remaining=initial*math.exp(-0.693*time/half_life)>>> f"Remaining quantity of Sr-90: {remaining}"'Remaining quantity of Sr-90: 16.22044604811303'

As you can see, the half-life is set to 38.1 and the duration is set to 100 years. You can use math.exp to simplify the equation. By substituting the values to the equation you can find that, after 100 years, 16.22mg of Sr-90 remains.

Logarithmic Functions

Logarithmic functions can be considered the inverse of exponential functions. They are denoted in the following form:

General Logarithmic FunctionGeneral Logarithmic Function

Here a is the base of the logarithm, which can be any number. You learned about exponential functions in a previous section. Exponential functions can be expressed in the form of logarithmic functions and vice versa.

Python Natural Log With log()

The natural logarithm of a number is its logarithm to the base of the mathematical constant e, or Euler’s number:

Natural Logarithmic FunctionNatural Logarithmic Function

As with the exponential function, natural log uses the constant e. It’s generally depicted as f(x) = ln(x), where e is implicit.

You can use the natural log in the same way that you use the exponential function. It’s used to calculate values such as the rate of population growth or the rate of radioactive decay in elements.

log() has two arguments. The first one is mandatory and the second one is optional. With one argument you can get the natural log (to the base e) of the input number:

>>>
>>> math.log(4)1.3862943611198906>>> math.log(3.4)1.2237754316221157

However, the function returns a ValueError if you input a non-positive number:

>>>
>>> math.log(-3)Traceback (most recent call last):
  File "<stdin>", line 1, in <module>ValueError: math domain error

As you can see, you can’t input a negative value to log(). This is because log values are undefined for negative numbers and zero.

With two arguments, you can calculate the log of the first argument to the base of the second argument:

>>>
>>> math.log(math.pi,2)1.651496129472319>>> math.log(math.pi,5)0.711260668712669

You can see how the value changes when the log base is changed.

Understand log2() and log10()

The Python math module also provides two separate functions that let you calculate the log values to the base of 2 and 10:

  1. log2() is used to calculate the log value to the base 2.
  2. log10() is used to calculate the log value to the base 10.

With log2() you can get the log value to the base 2:

>>>
>>> math.log2(math.pi)1.6514961294723187>>> math.log(math.pi,2)1.651496129472319

Both functions have the same objective, but the Python documentation notes that log2() is more accurate than using log(x, 2).

You can calculate the log value of a number to base 10 with log10():

>>>
>>> math.log10(math.pi)0.4971498726941338>>> math.log(math.pi,10)0.4971498726941338

The Python documentation also mentions that log10() is more accurate than log(x, 10) even though both functions have the same objective.

Practical Example With Natural Log

In a previous section, you saw how to use math.exp() to calculate the remaining amount of a radioactive element after a certain period of time. With math.log(), you can find the half-life of an unknown radioactive element by measuring the mass at an interval. The following equation can be used to calculate the half-life of a radioactive element:

Half Life Equation of a Radioactive ElementRadioactive Decay Equation

By rearranging the radioactive decay formula, you can make the half-life (T) the subject of the formula. The variables of the given formula are as follows:

  • T is the half-life of the decaying quantity.
  • N(0) is the initial quantity of the substance.
  • N(t) is the quantity that remains and has not yet decayed after a period of time (t).
  • ln is the natural log.

You can substitute the known values to the equation to calculate the half-life of a radioactive substance.

For example, imagine you are studying an unidentified radioactive element sample. When it was discovered 100 years ago, the sample size was 100mg. After 100 years of decay, only 16.22mg is remaining. Using the formula above, you can calculate the half-life of this unknown element:

>>>
>>> initial=100>>> remaining=16.22>>> time=100>>> half_life=(-0.693*time)/math.log(remaining/initial)>>> f"Half-life of the unknown element: {half_life}"'Half-life of the unknown element: 38.09942398335152'

You can see that the unknown element has a half-life of roughly 38.1 years. Based on this information, you can identify the unknown element as strontium-90.

Other Important math Module Functions

The Python math module has many useful functions for mathematical calculations, and this article only covered a few of them in depth. In this section, you will briefly learn about some of the other important functions available in the math module.

Calculate the Greatest Common Divisor

The greatest common divisor (GCD) of two positive numbers is the largest positive integer that divides both numbers without a remainder.

For example, the GCD of 15 and 25 is 5. You can divide both 15 and 25 by 5 without any remainder. There is no greater number that does the same. If you take 15 and 30, then the GCD is 15 because both 15 and 30 can be divided by 15 without a remainder.

You don’t have to implement your own functions to calculate GCD. The Python math module provides a function called math.gcd() that allows you to calculate the GCD of two numbers. You can give positive or negative numbers as input, and it returns the appropriate GCD value. You can’t input a decimal number, however.

Calculate the Sum of Iterables

If you ever want to find the sum of the values of an iterable without using a loop, then math.fsum() is probably the easiest way to do so. You can use iterables such as arrays, tuples, or lists as input and the function returns the sum of the values. A built-in function called sum() lets you calculate the sum of iterables as well, but fsum() is more accurate than sum(). You can read more about that in the documentation.

Calculate the Square Root

The square root of a number is a value that, when multiplied by itself, gives the number. You can use math.sqrt() to find the square root of any positive real number (integer or decimal). The return value is always a float value. The function will throw a ValueError if you try to enter a negative number.

Convert Angle Values

In real-life scenarios as well as in mathematics, you often come across instances where you have to measure angles to perform calculations. Angles can be measured either by degrees or by radians. Sometimes you have to convert degrees to radians and vice versa. The math module provides functions that let you do so.

If you want to convert degrees to radians, then you can use math.radians(). It returns the radian value of the degree input. Likewise, if you want to convert radians to degrees, then you can use math.degrees().

Calculate Trigonometric Values

Trigonometry is the study of triangles. It deals with the relationship between angles and the sides of a triangle. Trigonometry is mostly interested in right-angled triangles (in which one internal angle is 90 degrees), but it can also be applied to other types of triangles. The Python math module provides very useful functions that let you perform trigonometric calculations.

You can calculate the sine value of an angle with math.sin(), the cosine value with math.cos(), and the tangent value with math.tan(). The math module also provides functions to calculate arc sine with math.asin(), arc cosine with math.acos(), and arc tangent with math.atan(). Finally, you can calculate the hypotenuse of a triangle using math.hypot().

New Additions to the math Module in Python 3.8

With the release of Python version 3.8, a few new additions and changes have been made to the math module. The new additions and changes are as follows:

  • comb(n, k) returns the number of ways to choose k items from n items without repetition and without particular order.

  • perm(n, k) returns the number of ways to choose k items from n items without repetition and with order.

  • isqrt() returns the integer square root of a non-negative integer.

  • prod() calculates the product of all of the elements in the input iterable. As with fsum(), this method can take iterables such as arrays, lists, or tuples.

  • dist() returns the Euclidean distance between two points p and q, each given as a sequence (or iterable) of coordinates. The two points must have the same dimension.

  • hypot() now handles more than two dimensions. Previously, it supported a maximum of two dimensions.

cmath vs math

A complex number is a combination of a real number and an imaginary number. It has the formula of a + bi, where a is the real number and bi is the imaginary number. Real and imaginary numbers can be explained as follows:

  • A real number is literally any number you can think of.
  • An imaginary number is a number that gives a negative result when squared.

A real number can be any number. For example, 12, 4.3, -19.0 are all real numbers. Imaginary numbers are shown as i. The following image shows an example of a complex number:

Complex NumberComplex Number

In the example above, 7 is the real number and 3i is the imaginary number. Complex numbers are mostly used in geometry, calculus, scientific calculations, and especially in electronics.

The functions of the Python math module aren’t equipped to handle complex numbers. However, Python provides a different module that can specifically deal with complex numbers, the cmath module. The Python math module is complemented by the cmath module, which implements many of the same functions but for complex numbers.

You can import the cmath module as follows:

>>>
>>> importcmath

Since the cmath module is also packaged with Python, you can import it the same way you imported the math module. Before you work with the cmath module, you have to know how to define a complex number. You can define a complex number as follows:

>>>
>>> c=2+3j>>> c(2+3j)>>> type(c)<class 'complex'>

As you can see, you can determine that a number is indeed complex by using type().

Note: In mathematics, the imaginary unit is usually denoted i. In some fields, it’s more customary to use j for the same thing. In Python, you use j to denote imaginary numbers.

Python also provides a special built-in function called complex() that lets you create complex numbers. You can use complex() as follows:

>>>
>>> c=complex(2,3)>>> c(2+3j)>>> type(c)<class 'complex'>

You can use either method to create complex numbers. You can also use the cmath module to calculate mathematical functions for complex numbers as follows:

>>>
>>> cmath.sqrt(c)(1.8581072140693775+0.6727275964137814j)>>> cmath.log(c)(1.3622897515267103+0.6947382761967031j)>>> cmath.exp(c)(-16.091399670844+12.02063434789931j)

This example shows you how to calculate the square root, logarithmic value, and exponential value of a complex number. You can read the documentation if you want to learn more about the cmath module.

NumPy vs math

Several notable Python libraries can be used for mathematical calculations. One of the most prominent libraries is Numerical Python, or NumPy. It is mainly used in scientific computing and in data science fields. Unlike the math module, which is part of the standard Python release, you have to install NumPy in order to work with it.

The heart of NumPy is the high-performance N-dimensional (multidimensional) array data structure. This array allows you to perform mathematical operations on an entire array without looping over the elements. All of the functions in the library are optimized to work with the N-dimensional array objects.

Both the math module and the NumPy library can be used for mathematical calculations. NumPy has several similarities with the math module. NumPy has a subset of functions, similar to math module functions, that deal with mathematical calculations. Both NumPy and math provide functions that deal with trigonometric, exponential, logarithmic, hyperbolic and arithmetic calculations.

There are also several fundamental differences between math and NumPy. The Python math module is geared more towards working with scalar values, whereas NumPy is better suited for working with arrays, vectors, and even matrices.

When working with scalar values, math module functions can be faster than their NumPy counterparts. This is because the NumPy functions convert the values to arrays under the hood in order to perform calculations on them. NumPy is much faster when working with N-dimensional arrays because of the optimizations for them. Except for fsum() and prod(), the math module functions can’t handle arrays.

Conclusion

In this article, you learned about the Python math module. The module provides useful functions for performing mathematical calculations that have many practical applications.

In this article you’ve learned:

  • What the Python math module is
  • How to use math functions with practical examples
  • What the constants of the math module, including pi, tau, and Euler’s number are
  • What the differences between built-in functions and math functions are
  • What the differences between math, cmath, and NumPy are

Understanding how to use the math functions is the first step. Now it’s time to start applying what you learned to real-life situations. If you have any questions or comments, then please leave them in the comments section below.


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


Stéphane Wirtel: Contribution to PythonIreland

$
0
0
At the end of February, I was in Limerick to help the PythonIreland team for the PyCon Limerick held there during the weekend of February 29th. And because I wanted to help them, I have started to rewrite the web site of PyCon Limerick 2020. The current version of PyCon Limerick uses a Wordpress instance, I have no issues with the set up. But I prefer to work with a static site, and with some other members of the team, I have started to work on a static version with Hugo.

Python Software Foundation: New pip resolver to roll out this year

$
0
0

The developers of pip are in the process of developing a new resolver for pip (as we announced on the PSF blog last year). We aim to roll it out later this year. As part of that work, there will be some major changes to how pip determines what to install, based on package requirements. In this post we share:

What will change
What you can do to help
When this will be happening

To understand what pip does and why we’re working on it, please read our earlier overview post.

What will change

The most significant changes to the resolver will be:

  • It will reduce inconsistency: it will no longer install a combination of packages that is mutually inconsistent. At the moment, it is possible for pip to install a package which does not satisfy the declared requirements of another installed package. For example, right now, pip install "six<1.12" "virtualenv==20.0.2" does the wrong thing, “successfully” installing six==1.11, even though virtualenv==20.0.2 requires six>=1.12.0,<2 (defined here). The new resolver would, instead, outright reject installing anything if it got that input.
  • It will be stricter - if you ask pip to install two packages with incompatible requirements, it will refuse (rather than installing a broken combination, like it does now).

Also, this is a major change to a key part of pip - it’s quite possible there will initially be bugs. We would like to make sure that those get caught before people start using the new version in production.

(For deep technical details, see this in-progress GitHub milestone.)

What you can do to help

We recognize that everyone’s work is being disrupted by the COVID-19 pandemic, and that many data scientists and medical researchers use Python and pip in their work. We want to make the upgrade process as smooth and bug-free as possible for our users; if you can help us, you’ll be helping each other.

  1. First and most fundamentally, please help us understand how you use pip by talking with our user experience researchers. You can do this right now! You can take a survey, or have a researcher interview you over a video call. Please sign up and spread the word to anyone who uses pip (even a little bit).

  2. Right now, even before we release the new resolver as a beta, you can help by running pip check on your current environment. This will report if you have any inconsistencies in your set of installed packages. Having a clean installation will make it much less likely that you will hit issues when the new resolver is released (and may address hidden problems in your current environment!). If you run pip check and run into stuff you can’t figure out, please ask for help in our issuetracker or chat.

  3. Please make time to test the new version of pip, probably in May (see below). While we have tried to make sure that pip’s test suite covers as many cases as we can, we are very aware that there are people using pip with many different workflows and build processes, and we will not be able to cover all of those without your help.

    • If you use pip to install your software, try out the new resolver and let us know if it works for you.
    • If you have a build pipeline that depends on pip installing your dependencies for you, check that the new resolver does what you need.
    • Run your project’s CI (test suite, build process, etc.) using the new resolver, and let us know of any issues.
    • If you have encountered resolver issues with pip in the past, check whether the new resolver fixes them. Also, let us know if the new resolver has issues with any workarounds you put in to address the current resolver’s limitations. We’ll need to ensure that people can transition off such workarounds smoothly.

    As you and your colleagues plan for the next few months, please set aside time, ideally in May, to test the new resolver and tell us whether it breaks anything for your setup by filling out this survey. If you maintain an open source project or use pip at your job, you can make a ticket now and put it in your backlog.

  4. Spread the word! If you know of other people who rely on pip, who might not have seen this message, let them know. You can do this right now.

  5. And if you develop or support a tool that wraps pip or uses it to deliver part of your functionality, please make time to test your integration with our beta in May, and sure that the new resolver doesn’t cause you any issues. (It shouldn’t, as the resolver is an internal component of pip and shouldn’t be visible to people embedding pip, but we’d like to be sure of that.)

When this will be happening

We intend to release the new resolver early in the second half of 2020. We will provide alpha and beta releases before that point as the work progresses (probably starting in May), and we’ll provide a GitHub issue tracker and an email address where you can report bugs. We would appreciate as much feedback as we can get on the betas when they become available.

(We were already working as a distributed team. The COVID-19 pandemic and related disruptions are affecting us – for instance, we were aiming to meet, work together, and test and discuss our work at PyCon US. But we still anticipate releasing the new resolver in the second half of 2020.)

To find out when the new beta is available for testing, and how to report problems, subscribe to the pypi-announce mailing list. It’s very low-traffic.

(Why now? The Python Software Foundation’s Packaging Working Group obtained funding for this work because it’s sorely needed; many other features and tools are blocked waiting for this fix. We’ve spent years addressing technical debt in pip so we can properly untie this knot and refurbish the resolver. We started this chunk of donor-funded work on pip a few months ago and it’s now gotten far enough that we can make this pre-announcement.)

Thank you to the pip and PyPA maintainers, to the PSF and the Packaging WG, and to all the contributors and volunteers who work on or use Python packaging tools. And thank you to Mozilla (through its Mozilla Open Source Support Awards) and to the Chan Zuckerberg Initiative DAF, an advised fund of Silicon Valley Community Foundation, for funding enabling this work!

Codementor: Simple Speech to Text Converter Using Speech Recognization in Python

$
0
0
In this part, I'm going to share small script to create speech to text converter in python using google Speech Recognition module. Here is the code - ``` import speech_recognition as sr r =...

Python Insider: Python 3.9.0a5 is now available for testing

$
0
0
On behalf of the entire Python development community, and the currently serving Python release team in particular, I’m pleased to announce the release of Python 3.9.0a5. Get it here:


This is an early developer preview of Python 3.9


Python 3.9 is still in development. This releasee, 3.9.0a5 is the fifth of six planned alpha releases. Alpha releases are intended to make it easier to test the current state of new features and bug fixes and to test the release process. During the alpha phase, features may be added up until the start of the beta phase (2020-05-18) and, if necessary, may be modified or deleted up until the release candidate phase (2020-08-10). Please keep in mind that this is a preview release and its use is not recommended for production environments.


Major new features of the 3.9 series, compared to 3.8


Many new features for Python 3.9 are still being planned and written. Among the new major new features and changes so far:
  • PEP 584, Union Operators in dict
  • PEP 593, Flexible function and variable annotations
  • PEP 602, Python adopts a stable annual release cadence
  • BPO 38379, garbage collection does not block on resurrected objects;
  • BPO 38692, os.pidfd_open added that allows process management without races and signals;
  • BPO 39926, Unicode support updated to version 13.0.0
  • BPO 1635741, when Python is initialized multiple times in the same process, it does not leak memory anymore
  • A number of Python builtins (range, tuple, set, frozenset, list) are now sped up using PEP 570 vectorcall
  • A number of standard library modules (audioop, ast, grp, _hashlib, pwd, _posixsubprocess, random, select, struct, termios, zlib) are now using the stable ABI defined by PEP 384.
  • (Hey, fellow core developer, if a feature you find important is missing from this list, let Łukasz know.)
The next pre-release, the last alpha release of Python 3.9, will be 3.9.0a6. It is currently scheduled for 2020-04-22. Until then, stay safe!

Wing Tips: Remote Python Development on AWS with Wing Pro

$
0
0

In this Wing Tip we'll start looking at how to use Wing Pro to remotely develop Python code running on an AWS instance. With minimal configuration, Wing Pro can edit, debug, test, inspect, and navigate Python code residing on an AWS instance, as if it were on the local host.

Minimum Requirements

You will need an AWS instance that has Python installed on it, is running 32-bit or 64-bit Intel Linux, and that you can connect to using OpenSSH or PuTTY. PuTTY is recommended on Windows because it tends to be prone to fewer problems. You will need the following in order to configure Wing Pro to use your AWS instance:

(1) The user name and static IP address or DNS name used to connect to the AWS instance. Amazon Lightsail typically uses an IP address while EC2 and other variants of AWS may provide a DNS name as well. The static IP address will work in any case.

(2) The SSH key pair in a *.pem file, as downloaded from AWS.

If you do not already have Wing Pro installed, download it now.

Setting up AWS

If you already have an AWS instance to work with, you can skip this section.

Amazon Lightsail is the easiest way to get an AWS instance, in about 5 minutes. You will need to set up an account. Then create a Linux/Unix instance, selecting the OSOnly option and the most recent Ubuntu or any other Intel Linux with Python 2 or 3 on it.

While setting up your instance, you can download your SSH key pair under the AWS SSHkeypairmanager. You'll need this on your local machine, where Wing is running, in order to be able to connect to the instance.

After the instance is created, it will remain in pending state for a minute or so. Once it is up and running, create a static IP address under the Network tab in the AWS Lightsail management area and attach it to your instance.

At this point you have all that is needed to start using Wing Pro with AWS: (1) The SSH key pair that you downloaded, and (2) the user name and IP address, which are shown on the Lightsail instance management page.

Testing the SSH Connection

Before trying to use your new instance from Wing Pro, you should first try to connect using ssh or PuTTY's plink.exe on the command line, to make sure those are working. This is important because Wing invokes those command lines to connect to the instance.

OpenSSH

On Linux or macOS using ssh, you need to make your *.pem SSH key pair file readable only by the user running Wing, for example with:

chmod 600 aws.pem

Otherwise, ssh will reject it as potentially compromised.

Once that is done, try connecting as follows, substituting the actual path to your downloaded SSH key pair and your instance's username and IP address or DNS name:

ssh -i /path/to/mykey.pem ubuntu@11.22.33.44

You will be asked to add the instance's identity to your known hosts file, which you should do by typing yes. If this is not done, ssh will fail to connect and Wing will also not be able to connect to the instance.

PuTTY

With PuTTY on Windows, you will need to first convert the SSH key to a format that PuTTY can use. This is done by launching puttygen, pressing the Load button to read the *.pem SSH key file you downloaded from the AWS management site, and then using SavePrivateKey to write a *.ppk file.

Then you invoke plink.exe to connect to the AWS instance as follows, substituting in the actual path to your downloaded SSH key pair and the correct username and IP address or DNS name for the AWS instance:

plink.exe -i C:\path\to\mykey.ppk ubuntu@11.22.33.44

You will be asked to accept the AWS instance's identity the first time you connect, and this must be done before Wing's remote development support will work with the AWS instance.

Creating a Wing Project

Now you're ready to create a project in Wing Pro. This is done with NewProject from the Project menu. Select ConnecttoRemoteHostviaSSH as your project type. Then enter an identifier for the remote host (any short string to identify it in Wing's UI), and the user name and IP address or DNS name used to connect to the host:

/images/blog/aws-1/new-project.png

As in the above example, PythonExecutable will usually be Usedefault, which first tries python3 and then python. If Python is not on the PATH on your AWS instance or you want to specify a particular Python executable or activate a virtual environment, you can do this here.

You will also need to point Wing at the SSH key pair file you downloaded from AWS earlier. This is done under the Options tab using the PrivateKey field as follows:

/images/blog/aws-1/private-key-file.png

Pressing OK in the NewProject dialog will create and configure the project, connect to the remote instance, install Wing's remote agent, and then offer to add source directories to the project or save the new project file:

/images/blog/aws-1/new-project-confirm.png

If you already have source code on the AWS instance, press AddDirectory one or more times to add directories to the project. Typically, you want to add the directories that contain code you plan to work on, and leave out directories that contain Python, the standard libraries, and other modules and packages that you may use. Wing can find those as needed, through the Python Path.

If you are working with a blank new AWS instance, add the home directory to your project to get started. This can be changed later as needed.

Finally, save the project to local disk. The project is now ready to use.

Testing a Hello World

To try out a simple example of editing and debugging code on the remote AWS instance, create a file helloworld.py temporarily on the instance. This is done by right-clicking on one of the files in the Project tool in Wing Pro and selecting CreateNewFile. Enter the file name (in some key bindings this is in the data entry area at the bottom of Wing's window) and type or paste the following into the new file:

importtimeprint("Hello World! {}".format(time.time()))

After saving the file, set a breakpoint on the second line by clicking on the leftmost margin in the editor:

/images/blog/aws-1/breakpoint.png

Then select Starting/Continue from the Debug menu to start debug, or use the green play icon play in the toolbar.

There is a slight delay to get the process started, depending on your network distance from the AWS instance, but then you should see Wing stop on the breakpoint:

/images/blog/aws-1/breakpoint-stop.png

There's not much to see here, but you can poke around a little in the live runtime state of the paused debug process, using Wing Pro's DebugConsole, from the Tools menu:

/images/blog/aws-1/debug-console.png

Once you continue debugging, the process will exit and print to the DebugI/O tool:

/images/blog/aws-1/debug-io.png

That's it for now! We'll be back soon with more Wing Tips for Wing Python IDE.

As always, please don't hesitate to email support@wingware.com if you run into problems or have any questions.

Viewing all 22422 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>