These special parameters allow functions to take arbitrary amounts of positional and keyword arguments. The names args and kwargs are purely convention, and could be named any other valid variable name. The special functionality comes from the single and double asterisks (*). If both are used in a function signature, *args must appear before **kwargs.
Single asterisk
*args will ingest an arbitrary amount of positional arguments, and store it in a tuple. If there are parameters after *args in the parameter list with no default value, they will become required keyword arguments by default.
Double asterisk
**kwargs will ingest an arbitrary amount of keyword arguments, and store it in a dictionary. There can be no additional parameters after **kwargs in the parameter list.
Use cases
- Decorators (see /tag decorators)
- Inheritance (overriding methods)
- Future proofing (in the case of the first two bullet points, if the parameters change, your code won't break)
- Flexibility (writing functions that behave like dict() or print())  
See /tag positional-keyword for information about positional and keyword arguments
Python provides the ability to run multiple tasks and coroutines simultaneously with the use of the asyncio library, which is included in the Python standard library.
This works by running these coroutines in an event loop, where the context of the running coroutine switches periodically to allow all other coroutines to run, thus giving the appearance of running at the same time. This is different to using threads or processes in that all code runs in the main process and thread, although it is possible to run coroutines in other threads.
To call an async function we can either await it, or run it in an event loop which we get from asyncio.
To create a coroutine that can be used with asyncio we need to define a function using the async keyword:
async def main():
    await something_awaitable()await something_awaitable() directly from within the function. If this were a non-async function, it would raise the exception SyntaxError: 'await' outside async function
To run the top level async function from outside the event loop we need to use asyncio.run(), like this:
import asyncio
async def main():
    await something_awaitable()
asyncio.run(main())asyncio.run(), where we appear to be calling main(), this does not execute the code in main. Rather, it creates and returns a new coroutine object (i.e main() is not main()) which is then handled and run by the event loop via asyncio.run().
To learn more about asyncio and its use, see the asyncio documentation.
Imagine that you're coding a Discord bot and every time somebody uses a command, you need to get some information from a database. But there's a catch: the database servers are acting up today and take a whole 10 seconds to respond. If you do not use asynchronous methods, your whole bot will stop running until it gets a response from the database. How do you fix this? Asynchronous programming.
What is asynchronous programming?
An asynchronous program utilises the async and await keywords. An asynchronous program pauses what it's doing and does something else whilst it waits for some third-party service to complete whatever it's supposed to do. Any code within an async context manager or function marked with the await keyword indicates to Python, that whilst this operation is being completed, it can do something else. For example:
import discord
# Bunch of bot code
async def ping(ctx):
    await ctx.send("Pong!")awaiting it. This tells Python that this step must be completed before it can do anything else. Common examples of blocking operations, as simple as they may seem, include: outputting text, adding two numbers and appending an item onto a list. Most common Python libraries have an asynchronous version available to use in asynchronous contexts.
async libraries
- The standard async library - asyncio
- Asynchronous web requests - aiohttp
- Talking to PostgreSQL asynchronously - asyncpg
- MongoDB interactions asynchronously - motor
- Check out this list for even more!
Classes are used to create objects that have specific behavior.
Every object in Python has a class, including lists, dictionaries and even numbers. Using a class to group code and data like this is the foundation of Object Oriented Programming. Classes allow you to expose a simple, consistent interface while hiding the more complicated details. This simplifies the rest of your program and makes it easier to separately maintain and debug each component.
Here is an example class:
class Foo:
    def __init__(self, somedata):
        self.my_attrib = somedata
    def show(self):
        print(self.my_attrib)To use a class, you need to instantiate it. The following creates a new object named bar, with Foo as its class.
bar = Foo('data')
bar.show()We can access any of Foo's methods via bar.my_method(), and access any of bars data via bar.my_attribute.
Although most methods are tied to an object instance, it can sometimes be useful to create a method that does something with the class itself. To achieve this in Python, you can use the @classmethod decorator. This is often used to provide alternative constructors for a class.
For example, you may be writing a class that takes some magic token (like an API key) as a constructor argument, but you sometimes read this token from a configuration file. You could make use of a @classmethod to create an alternate constructor for when you want to read from the configuration file.
class Bot:
    def __init__(self, token: str):
        self._token = token  
    @classmethod
    def from_config(cls, config: dict) -> Bot:
        token = config['token']
        return cls(token)
# now we can create the bot instance like this
alternative_bot = Bot.from_config(default_config)
# but this still works, too
regular_bot = Bot("tokenstring")@classmethod. A more in-depth explanation can be found here.The assignment operator (=) is used to assign variables.
x = 5
print(x)  # Prints 5==) is used to compare values.
if x == 5:
    print("The value of x is 5")Looking to contribute to Open Source Projects for the first time? Want to add a feature or fix a bug on the bots on this server? We have on-going projects that people can contribute to, even if you've never contributed to open source before!
Projects to Contribute to - Sir Lancebot - our fun, beginner-friendly bot - Python - our utility & moderation bot - Site - resources, guides, and more
Where to start 1. Read our contribution guide 2. Chat with us in <#635950537262759947> if you're ready to jump in or have any questions 3. Open an issue or ask to be assigned to an issue to work on
Often you may find the need to use checks that don't exist by default in discord.py. Fortunately, discord.py provides discord.ext.commands.check which allows you to create you own checks like this:
from discord.ext.commands import check, Context
def in_any_channel(*channels):
  async def predicate(ctx: Context):
    return ctx.channel.id in channels
  return check(predicate)predicate here, is used to perform the actual check on the command, and check logic should go in this function. It must be an async function, and always provides a single commands.Context argument which you can use to create check logic. This check function should return a boolean value indicating whether the check passed (return True) or failed (return False).
The check can now be used like any other commands check as a decorator of a command, such as this:
@bot.command(name="ping")
@in_any_channel(728343273562701984)
async def ping(ctx: Context):
  ...ping command to only be used in the channel 728343273562701984. If this check function fails it will raise a CheckFailure exception, which can be handled in your error handler.Cooldowns can be used in discord.py to rate-limit. In this example, we're using it in an on_message.
from discord.ext import commands
message_cooldown = commands.CooldownMapping.from_cooldown(1.0, 60.0, commands.BucketType.user)
@bot.event
async def on_message(message):
    bucket = message_cooldown.get_bucket(message)
    retry_after = bucket.update_rate_limit()
    if retry_after:
        await message.channel.send(f"Slow down! Try again in {retry_after} seconds.")
    else:
        await message.channel.send("Not ratelimited!")from_cooldown takes the amount of update_rate_limit()s needed to trigger the cooldown, the time in which the cooldown is triggered, and a BucketType.
To learn more about how to create custom help commands in discord.py by subclassing the help command, please see this tutorial by Stella#2000
When trying to install a package via pip, it's recommended to invoke pip as a module: python -m pip install your_package.
Why would we use python -m pip instead of pip?
Invoking pip as a module ensures you know which pip you're using. This is helpful if you have multiple Python versions. You always know which Python version you're installing packages to.
Note
The exact python command you invoke can vary. It may be python3 or py, ensure it's correct for your system.
A decorator is a function that modifies another function.
Consider the following example of a timer decorator:
>>> import time
>>> def timer(f):
...     def inner(*args, **kwargs):
...         start = time.time()
...         result = f(*args, **kwargs)
...         print('Time elapsed:', time.time() - start)
...         return result
...     return inner
...
>>> @timer
... def slow(delay=1):
...     time.sleep(delay)
...     return 'Finished!'
...
>>> print(slow())
Time elapsed: 1.0011568069458008
Finished!
>>> print(slow(3))
Time elapsed: 3.000307321548462
Finished!More information:
- Corey Schafer's video on decorators
- Real python article
The Python defaultdict type behaves almost exactly like a regular Python dictionary, but if you try to access or modify a missing key, the defaultdict will automatically insert the key and generate a default value for it.
While instantiating a defaultdict, we pass in a function that tells it how to create a default value for missing keys.
>>> from collections import defaultdict
>>> my_dict = defaultdict(int)
>>> my_dict
defaultdict(<class 'int'>, {})In this example, we've used the int class which returns 0 when called like a function, so any missing key will get a default value of 0. You can also get an empty list by default with list or an empty string with str.
>>> my_dict["foo"]
0
>>> my_dict["bar"] += 5
>>> my_dict
defaultdict(<class 'int'>, {'foo': 0, 'bar': 5})docs to learn even more!Often while using dictionaries in Python, you may run into KeyErrors. This error is raised when you try to access a key that isn't present in your dictionary. Python gives you some neat ways to handle them.
The dict.get method will return the value for the key if it exists, and None (or a default value that you specify) if the key doesn't exist. Hence it will never raise a KeyError.
>>> my_dict = {"foo": 1, "bar": 2}
>>> print(my_dict.get("foobar"))
None>>> print(my_dict.get("foobar", 3))
3KeyErrors gracefully are the dict.setdefault method and collections.defaultdict (check out the !defaultdict tag).Dictionary comprehensions (dict comps) provide a convenient way to make dictionaries, just like list comps:
>>> {word.lower(): len(word) for word in ('I', 'love', 'Python')}
{'i': 1, 'love': 4, 'python': 6}One can use a dict comp to change an existing dictionary using its items method
>>> first_dict = {'i': 1, 'love': 4, 'python': 6}
>>> {key.upper(): value * 2 for key, value in first_dict.items()}
{'I': 2, 'LOVE': 8, 'PYTHON': 12}Using free hosting options like repl.it for continuous 24/7 bot hosting is strongly discouraged. Instead, opt for a virtual private server (VPS) or use your own spare hardware if you'd rather not pay for hosting.
See our Discord Bot Hosting Guide on our website that compares many hosting providers, both free and paid.
You may also use <#965291480992321536> to discuss different discord bot hosting options.
A docstring is a string - always using triple quotes - that's placed at the top of files, classes and functions. A docstring should contain a clear explanation of what it's describing. You can also include descriptions of the subject's parameter(s) and what it returns, as shown below:
def greet(name: str, age: int) -> str:
    """
    Return a string that greets the given person, using their name and age.
    :param name: The name of the person to greet.
    :param age: The age of the person to greet.
    :return: The greeting.
    """
    return f"Hello {name}, you are {age} years old!"inspect.getdoc function, from the built-in inspect module, or by accessing the .__doc__ attribute. inspect.getdoc is often preferred, as it clears indents from the docstring.
For the last example, you can print it by doing this: print(inspect.getdoc(greet)).
For more details about what a docstring is and its usage, check out this guide by Real Python, or the official docstring specification.
.env (dotenv) files are a type of file commonly used for storing application secrets and variables, for example API tokens and URLs, although they may also be used for storing other configurable values. While they are commonly used for storing secrets, at a high level their purpose is to load environment variables into a program.
Dotenv files are especially suited for storing secrets as they are a key-value store in a file, which can be easily loaded in most programming languages and ignored by version control systems like Git with a single entry in a .gitignore file.
In Python you can use dotenv files with the python-dotenv module from PyPI, which can be installed with pip install python-dotenv. To use dotenv files you'll first need a file called .env, with content such as the following:
TOKEN=a00418c85bff087b49f23923efe40aa5from dotenv import load_dotenv
load_dotenv()os.getenv() anywhere in your program, like this:
from os import getenv
my_token = getenv("TOKEN")Double-underscore methods, or "dunder" methods, are special methods defined in a class that are invoked implicitly. Like the name suggests, they are prefixed and suffixed with dunders. You've probably already seen some, such as the __init__ dunder method, also known as the "constructor" of a class, which is implicitly invoked when you instantiate an instance of a class.
When you create a new class, there will be default dunder methods inherited from the object class. However, we can override them by redefining these methods within the new class. For example, the default __init__ method from object doesn't take any arguments, so we almost always override that to fit our needs.
Other common dunder methods to override are __str__ and __repr__. __repr__ is the developer-friendly string representation of an object - usually the syntax to recreate it - and is implicitly called on arguments passed into the repr function. __str__ is the user-friendly string representation of an object, and is called by the str function. Note here that, if not overriden, the default __str__ invokes __repr__ as a fallback.
class Foo:
    def __init__(self, value):  # constructor
        self.value = value
    def __str__(self):
        return f"This is a Foo object, with a value of {self.value}!"  # string representation
    def __repr__(self):
        return f"Foo({self.value!r})"  # way to recreate this object
bar = Foo(5)
# print also implicitly calls __str__
print(bar)  # Output: This is a Foo object, with a value of 5!
# dev-friendly representation
print(repr(bar))  # Output: Foo(5)Another example: did you know that when you use the <left operand> + <right operand> syntax, you're implicitly calling <left operand>.__add__(<right operand>)? The same applies to other operators, and you can look at the operator built-in module documentation for more information!
When using JSON, you might run into the following error:
JSONDecodeError: Expecting value: line 1 column 1 (char 0)Whilst having empty data is no problem, the file itself may never be completely empty.
You most likely wanted to structure your JSON as a dictionary. To do this, edit your empty JSON file so that it instead contains {}.
Different data types are also supported. If you wish to read more on these, please refer to this article.
Ever find yourself in need of the current iteration number of your for loop? You should use enumerate! Using enumerate, you can turn code that looks like this:
index = 0
for item in my_list:
    print(f"{index}: {item}")
    index += 1for index, item in enumerate(my_list):
    print(f"{index}: {item}")The main purpose of Python virtual environments is to create an isolated environment for Python projects. This means that each project can have its own dependencies, such as third party packages installed using pip, regardless of what dependencies every other project has.
To see the current environment in use by Python, you can run:
>>> import sys
>>> sys.executable
'/usr/bin/python3'To see the environment in use by pip, you can do pip debug (pip3 debug for Linux/macOS). The 3rd line of the output will contain the path in use e.g. sys.executable: /usr/bin/python3.
If Python's sys.executable doesn't match pip's, then they are currently using different environments! This may cause Python to raise a ModuleNotFoundError when you try to use a package you just installed with pip, as it was installed to a different environment.
Why use a virtual environment?
- Resolve dependency issues by allowing the use of different versions of a package for different projects. For example, you could use Package A v2.7 for Project X and Package A v1.3 for Project Y.
- Make your project self-contained and reproducible by capturing all package dependencies in a requirements file. Try running pip freezeto see what you currently have installed!
- Keep your global site-packages/directory tidy by removing the need to install packages system-wide which you might only need for one project.
Further reading:
It's tempting to think that if statements always need a comparison operator like == or !=, but this isn't true.
If you're just checking if a value is truthy or falsey, you don't need == True or == False.
# instead of this...
if user_input.startswith('y') == True:
    my_func(user_input)
# ...write this
if user_input.startswith('y'):
    my_func(user_input)
# for false conditions, instead of this...
if user_input.startswith('y') == False:
    my_func(user_input)
# ...just use `not`
if not user_input.startswith('y'):
    my_func(user_input)is True or is False.A key part of the Python philosophy is to ask for forgiveness, not permission. This means that it's okay to write code that may produce an error, as long as you specify how that error should be handled. Code written this way is readable and resilient.
try:
    number = int(user_input)
except ValueError:
    print("failed to convert user_input to a number. setting number to 0.")
    number = 0try block should be as short as possible. Attempting to handle broad categories of unexpected exceptions can silently hide serious problems.
try:
    number = int(user_input)
    item = some_list[number]
except:
    print("An exception was raised, but we have no idea if it was a ValueError or an IndexError.")If you want to exit your code programmatically, you might think to use the functions exit() or quit(), however this is bad practice. These functions are constants added by the site module as a convenient method for exiting the interactive interpreter shell, and should not be used in programs.
You should use either SystemExit or sys.exit() instead.
There's not much practical difference between these two other than having to import sys for the latter. Both take an optional argument to provide an exit status.
Official documentation with the warning not to use exit() or quit() in source code.
Creating a Python string with your variables using the + operator can be difficult to write and read. F-strings (format-strings) make it easy to insert values into a string. If you put an f in front of the first quote, you can then put Python expressions between curly braces in the string.
>>> snake = "pythons"
>>> number = 21
>>> f"There are {number * 2} {snake} on the plane."
"There are 42 pythons on the plane."number * 2, Python will convert it to a string for you.As the largest Python community on Discord, we get hundreds of questions every day. Many of these questions have been asked before. We've compiled a list of the most frequently asked questions along with their answers, which can be found on our FAQ page.
You may have noticed that when doing arithmetic with floats in Python you sometimes get strange results, like this:
>>> 0.1 + 0.2
0.30000000000000004How you can avoid this You can use math.isclose to check if two floats are close, or to get an exact decimal representation, you can use the decimal or fractions module. Here are some examples:
>>> math.isclose(0.1 + 0.2, 0.3)
True
>>> decimal.Decimal('0.1') + decimal.Decimal('0.2')
Decimal('0.3')decimal.Decimal we enter the number we want as a string so we don't pass on the imprecision from the float.
For more details on why this happens check out this page in the python docs or this Computerphile video.
A specific word or set of words identified as a placeholder used in programming. They are used to name entities such as variables, functions, etc, whose exact identity is unimportant and serve only to demonstrate a concept, which is useful for teaching programming.
Common examples include foobar, foo, bar, baz, and qux.
Python has its own metasyntactic variables, namely spam, eggs, and bacon. This is a reference to a Monty Python sketch (the eponym of the language).
More information:
- History of foobar
- Monty Python sketch
In Python it's possible to attach an else clause to a for loop. The code under the else block will be run when the iterable is exhausted (there are no more items to iterate over). Code within the else block will not run if the loop is broken out using break.
Here's an example of its usage:
numbers = [1, 3, 5, 7, 9, 11]
for number in numbers:
    if number % 2 == 0:
        print(f"Found an even number: {number}")
        break
    print(f"{number} is odd.")
else:
    print("All numbers are odd. How odd.")When assigning a new name to a function, storing it in a container, or passing it as an argument, a common mistake made is to call the function. Instead of getting the actual function, you'll get its return value.
In Python you can treat function names just like any other variable. Assume there was a function called now that returns the current time. If you did x = now(), the current time would be assigned to x, but if you did x = now, the function now itself would be assigned to x. x and now would both equally reference the function.
Examples
# assigning new name
def foo():
    return 'bar'
def spam():
    return 'eggs'
baz = foo
baz() # returns 'bar'
ham = spam
ham() # returns 'eggs'# storing in container
import math
functions = [math.sqrt, math.factorial, math.log]
functions[0](25) # returns 5.0
# the above equivalent to math.sqrt(25)# passing as argument
class C:
    builtin_open = staticmethod(open)
# open function is passed
# to the staticmethod classWhen adding functions or classes to a program, it can be tempting to reference inaccessible variables by declaring them as global. Doing this can result in code that is harder to read, debug and test. Instead of using globals, pass variables or objects as parameters and receive return values.
Instead of writing
def update_score():
    global score, roll
    score = score + roll
update_score()def update_score(score, roll):
    return score + roll
score = update_score(score, roll)The communities page on our website contains a number of communities we have partnered with as well as a curated list of other communities relating to programming and technology.
Should I be using is or ==?
To check if two objects are equal, use the equality operator (==).
x = 5
if x == 5:
    print("x equals 5")
if x == 3:
    print("x equals 3")
# Prints 'x equals 5'is).
>>> list_1 = [1, 2, 3]
>>> list_2 = [1, 2, 3]
>>> if list_1 is [1, 2, 3]:
...    print("list_1 is list_2")
...
>>> reference_to_list_1 = list_1
>>> if list_1 is reference_to_list_1:
...    print("list_1 is reference_to_list_1")
...
list_1 is reference_to_list_1This is a statement that is only true if the module (your source code) it appears in is being run directly, as opposed to being imported into another module.  When you run your module, the __name__ special variable is automatically set to the string '__main__'. Conversely, when you import that same module into a different one, and run that, __name__ is instead set to the filename of your module minus the .py extension.
Example
# foo.py
print('spam')
if __name__ == '__main__':
    print('eggs')foo.py directly, both 'spam'and 'eggs' will be printed. Now consider this next example:
# bar.py
import foobar.py, it will execute the code in foo.py. First it will print 'spam', and then the if statement will fail, because __name__ will now be the string 'foo'.
Why would I do this?
- Your module is a library, but also has a special case where it can be run directly
- Your module is a library and you want to safeguard it against people running it directly (like what pipdoes)
- Your module is the main program, but has unit tests and the testing framework works by importing your module, and you want to avoid having your main code run during the test
In programming, there are two types of operations: - "In-place" operations, which modify the original object - "Out-of-place" operations, which returns a new object and leaves the original object unchanged
For example, the .sort() method of lists is in-place, so it modifies the list you call .sort() on:
>>> my_list = [5, 2, 3, 1]
>>> my_list.sort()  # Returns None
>>> my_list
[1, 2, 3, 5]sorted() function is out-of-place, so it returns a new list and leaves the original list unchanged:
>>> my_list = [5, 2, 3, 1]
>>> sorted_list = sorted(my_list)
>>> sorted_list
[1, 2, 3, 5]
>>> my_list
[5, 2, 3, 1]Indentation is leading whitespace (spaces and tabs) at the beginning of a line of code. In the case of Python, they are used to determine the grouping of statements.
Spaces should be preferred over tabs. To be clear, this is in reference to the character itself, not the keys on a keyboard. Your editor/IDE should be configured to insert spaces when the TAB key is pressed. The amount of spaces should be a multiple of 4, except optionally in the case of continuation lines.
Example
def foo():
    bar = 'baz'  # indented one level
    if bar == 'baz':
        print('ham')  # indented two levels
    return bar  # indented one levelif statement, and will only run if the if statement evaluates to True. The fifth and last line is like the 2nd and 3rd and will always run when the function is called. It effectively closes the if statement above as no more lines can be inside the if statement below that line.
Indentation is used after:
1. Compound statements (eg. if, while, for, try, with, def, class, and their counterparts)
2. Continuation lines
More Info 1. Indentation style guide 2. Tabs or Spaces? 3. Official docs on indentation
Inline codeblocks look like this. To create them you surround text with single backticks, so `hello` would become hello.
Note that backticks are not quotes, see this if you are struggling to find the backtick key.
If the wrapped code itself has a backtick, wrap it with two backticks from each side: ``back ` tick`` would become back ` tick.
For how to make multiline codeblocks see the !codeblock tag.
Intents are a feature of Discord that tells the gateway exactly which events to send your bot. Various features of discord.py rely on having particular intents enabled, further detailed in its documentation. Since discord.py v2.0.0, it has become mandatory for developers to explicitly define the values of these intents in their code.
There are standard and privileged intents. To use privileged intents like Presences, Server Members, and Message Content, you have to first enable them in the Discord Developer Portal. In there, go to the Bot page of your application, scroll down to the Privileged Gateway Intents section, and enable the privileged intents that you need. Standard intents can be used without any changes in the developer portal.
Afterwards in your code, you need to set the intents you want to connect with in the bot's constructor using the intents keyword argument, like this:
from discord import Intents
from discord.ext import commands
# Enable all standard intents and message content
# (prefix commands generally require message content)
intents = Intents.default()
intents.message_content = True
bot = commands.Bot(command_prefix="!", intents=intents)There are two common ways to iterate over a dictionary in Python. To iterate over the keys:
for key in my_dict:
    print(key)for key, val in my_dict.items():
    print(key, val)The Kindling projects page contains a list of projects and ideas programmers can tackle to build their skills and knowledge.
Do you ever find yourself writing something like this?
>>> squares = []
>>> for n in range(5):
...    squares.append(n ** 2)
[0, 1, 4, 9, 16]>>> [n ** 2 for n in range(5)]
[0, 1, 4, 9, 16]if clause:
>>> [n ** 2 for n in range(5) if n % 2 == 0]
[0, 4, 16]For more info, see this pythonforbeginners.com post.
Thanks to discord.py, sending local files as embed images is simple. You have to create an instance of discord.File class:
# When you know the file exact path, you can pass it.
file = discord.File("/this/is/path/to/my/file.png", filename="file.png")
# When you have the file-like object, then you can pass this instead path.
with open("/this/is/path/to/my/file.png", "rb") as f:
    file = discord.File(f)rb ('read binary') mode. Also, in this case, passing filename to it is not necessary.
Please note that filename must not contain underscores. This is a Discord limitation.
discord.Embed instances have a set_image method which can be used to set an attachment as an image:
embed = discord.Embed()
# Set other fields
embed.set_image(url="attachment://file.png")  # Filename here must be exactly same as attachment filename.await channel.send(file=file, embed=embed)discord.TextChannel for sending, but any instance of discord.abc.Messageable can be used for sending.Avoid adding to or removing from a collection, such as a list, as you iterate that collection in a for loop:
data = [1, 2, 3, 4]
for item in data:
    data.remove(item)
print(data)  # [2, 4] <-- every OTHER item was removed!In the example above, 1 is removed, shifting 2 to index 0. The loop then moves to index 1, removing 3 (and skipping 2!).
You can avoid this pitfall by: - using a list comprehension to produce a new list (as a way of filtering items):
data = [x for x in data if x % 2 == 0]while loop and .pop() (treating the list as a stack):
  while data:
    item = data.pop()The Discord gateway only dispatches events you subscribe to, which you can configure by using "intents."
The message content intent is what determines if an app will receive the actual content of newly created messages. Without this intent, discord.py won't be able to detect prefix commands, so prefix commands won't respond.
Privileged intents, such as message content, have to be explicitly enabled from the Discord Developer Portal in addition to being enabled in the code:
intents = discord.Intents.default() # create a default Intents instance
intents.message_content = True # enable message content intents
bot = commands.Bot(command_prefix="!", intents=intents) # actually pass it into the constructor/tag intents. If prefix commands are still not working, see /tag on-message-event.When you install a library through pip on Windows, sometimes you may encounter this error:
error: Microsoft Visual C++ 14.0 or greater is required. Get it with "Microsoft C++ Build Tools": https://visualstudio.microsoft.com/visual-cpp-build-tools/This means the library you're installing has code written in other languages and needs additional tools to install. To install these tools, follow the following steps: (Requires 6GB+ disk space)
1. Open https://visualstudio.microsoft.com/visual-cpp-build-tools/.
2. Click Download Build Tools >. A file named vs_BuildTools or vs_BuildTools.exe should start downloading. If no downloads start after a few seconds, click click here to retry.
3. Run the downloaded file. Click Continue to proceed.
4. Choose C++ build tools and press Install. You may need a reboot after the installation.
5. Try installing the library via pip again.
Imagine that you want to make all letters in a string upper case. Conveniently, strings have an .upper() method.
You might think that this would work:
>>> greeting = "hello"
>>> greeting.upper()
'HELLO'
>>> greeting
'hello'greeting didn't change. Why is that so?
That's because strings in Python are immutable. You can't change them, you can only pass around existing strings or create new ones.
>>> greeting = "hello"
>>> greeting = greeting.upper()
>>> greeting
'HELLO'greeting.upper() creates and returns a new string which is like the old one, but with all the letters turned to upper case.
int, float, complex, tuple, frozenset are other examples of immutable data types in Python.
Mutable data types like list, on the other hand, can be changed in-place:
>>> my_list = [1, 2, 3]
>>> my_list.append(4)
>>> my_list
[1, 2, 3, 4]Other examples of mutable data types in Python are dict and set. Instances of user-defined classes are also mutable.
For an in-depth guide on mutability see Ned Batchelder's video on names and values.
Default arguments in Python are evaluated once when the function is defined, not each time the function is called. This means that if you have a mutable default argument and mutate it, you will have mutated that object for all future calls to the function as well.
For example, the following append_one function appends 1 to a list
and returns it. foo is set to an empty list by default.
>>> def append_one(foo=[]):
...     foo.append(1)
...     return foo
...>>> append_one()
[1]
>>> append_one()
[1, 1]
>>> append_one()
[1, 1, 1]1 to our list foo. It does not
receive a new empty list on each call, it is the same list everytime.
To avoid this problem, you have to create a new object every time the function is called:
>>> def append_one(foo=None):
...     if foo is None:
...         foo = []
...     foo.append(1)
...     return foo
...
>>> append_one()
[1]
>>> append_one()
[1]Note:
- This behavior can be used intentionally to maintain state between calls of a function (eg. when writing a caching function).
- This behavior is not unique to mutable objects, all default arguments are evaulated only once when the function is defined.
A name is a piece of text that is bound to an object. They are a reference to an object. Examples are function names, class names, module names, variables, etc.
Note: Names cannot reference other names, and assignment never creates a copy.
x = 1  # x is bound to 1
y = x  # y is bound to VALUE of x
x = 2  # x is bound to 2
print(x, y) # 2 1y = x, the name y is being bound to the value of x which is 1. Neither x nor y are the 'real' name. The object 1 simply has multiple names. They are the exact same object.
>>> x = 1
x ━━ 1
>>> y = x
x ━━ 1
y ━━━┛
>>> x = 2
x ━━ 2
y ━━ 1You might think that the only way to bind a name to an object is by using assignment, but that isn't the case. All of the following work exactly the same as assignment:
-
import statements-
class and def-
for loop headers-
as keyword when used with except, import, and with- formal parameters in function headers
There is also del which has the purpose of unbinding a name.
More info
- Please watch Ned Batchelder's talk on names in python for a detailed explanation with examples
- Official documentation
If you've installed a package but you're getting a ModuleNotFoundError when you try to import it, it's likely that the environment where your code is running is different from the one where you did the installation.
You can read about Python environments at /tag environments and /tag venv.
Common causes of this problem include:
- You installed your package using pip install .... It could be that thepipcommand is not pointing to the environment where your code runs. For greater control, you could instead run pip as a module within the python environment you specify:python -m pip install <your_package>
- Your editor/ide is configured to create virtual environments automatically (PyCharm is configured this way by default).
There are three off-topic channels: - <#291284109232308226> - <#463035241142026251> - <#463035268514185226>
The channel names change every night at midnight UTC and are often fun meta references to jokes or conversations that happened on the server.
See our off-topic etiquette page for more guidance on how the channels should be used.
Registering the on_message event with @bot.event will override the default behavior of the event. This may cause prefix commands to stop working, because they rely on the default on_message event handler.
Instead, use @bot.listen to add a listener. Listeners get added alongside the default on_message handler which allows you to have multiple handlers for the same event. This means prefix commands can still be invoked as usual. Here's an example:
@bot.listen()
async def on_message(message):
    ...  # do stuff here
# Or...
@bot.listen('on_message')
async def message_listener(message):
    ...  # do stuff hereon_message handler with bot.process_commands(). However, this method isn't recommended as it does not allow you to add multiple on_message handlers.
If your prefix commands are still not working, it may be because you haven't enabled the message_content intent. See /tag message_content for more info.
The built-in function open() is one of several ways to open files on your computer. It accepts many different parameters, so this tag will only go over two of them (file and mode). For more extensive documentation on all these parameters, consult the official documentation. The object returned from this function is a file object or stream, for which the full documentation can be found here.
See also:
- !tags with for information on context managers
- !tags pathlib for an alternative way of opening files
- !tags seek for information on changing your position in a file  
The file parameter
This should be a path-like object denoting the name or path (absolute or relative) to the file you want to open.
An absolute path is the full path from your root directory to the file you want to open. Generally this is the option you should choose so it doesn't matter what directory you're in when you execute your module.
See !tags relative-path for more information on relative paths.
The mode parameter
This is an optional string that specifies the mode in which the file should be opened. There's not enough room to discuss them all, but listed below are some of the more confusing modes.
- 'r+'Opens for reading and writing (file must already exist)
- 'w+'Opens for reading and writing and truncates (can create files)
- 'x'Creates file and opens for writing (file must not already exist)
- 'x+'Creates file and opens for reading and writing (file must not already exist)
- 'a+'Opens file for reading and writing at end of file (can create files)
When checking if something is equal to one thing or another, you might think that this is possible:
# Incorrect...
if favorite_fruit == 'grapefruit' or 'lemon':
    print("That's a weird favorite fruit to have.")So, if you want to check if something is equal to one thing or another, there are two common ways:
# Like this...
if favorite_fruit == 'grapefruit' or favorite_fruit == 'lemon':
    print("That's a weird favorite fruit to have.")
# ...or like this.
if favorite_fruit in ('grapefruit', 'lemon'):
    print("That's a weird favorite fruit to have.")A parameter is a variable defined in a function signature (the line with def in it), while arguments are objects passed to a function call.
def square(n): # n is the parameter
    return n*n
print(square(5)) # 5 is the argumentNote that 5 is the argument passed to square, but square(5) in its entirety is the argument passed to print
If your code is too long to fit in a codeblock in Discord, you can paste your code here: https://paste.pythondiscord.com/
After pasting your code, save it by clicking the Paste! button in the bottom left, or by pressing CTRL + S. After doing that, you will be navigated to the new paste's page. Copy the URL and post it here so others can see it.
Python 3 comes with a new module named Pathlib. Since Python 3.6, pathlib.Path objects work nearly everywhere that os.path can be used, meaning you can integrate your new code directly into legacy code without having to rewrite anything. Pathlib makes working with paths way simpler than os.path does.
Feature spotlight:
- Normalizes file paths for all platforms automatically
- Has glob-like utilites (eg. Path.glob,Path.rglob) for searching files
- Can read and write files, and close them automatically
- Convenient syntax, utilising the /operator (e.g.Path('~') / 'Documents')
- Can easily pick out components of a path (eg. name, parent, stem, suffix, anchor)
- Supports method chaining
- Move and delete files
- And much more
More Info:
PEP 8 is the official style guide for Python. It includes comprehensive guidelines for code formatting, variable naming, and making your code easy to read. Professional Python developers are usually required to follow the guidelines, and will often use code-linters like flake8 to verify that the code they're writing complies with the style guide.
More information: - PEP 8 document - Our PEP 8 song! :notes:
Functions can take two different kinds of arguments. A positional argument is just the object itself. A keyword argument is a name assigned to an object.
Example
>>> print('Hello', 'world!', sep=', ')
Hello, world!'Hello' and 'world!' are positional arguments.
The sep=', ' is a keyword argument.
Note A keyword argument can be passed positionally in some cases.
def sum(a, b=1):
    return a + b
sum(1, b=5)
sum(1, 5) # same as abovepow() function.
The reverse is also true:
>>> def foo(a, b):
...     print(a, b)
...
>>> foo(a=1, b=2)
1 2
>>> foo(b=1, a=2)
2 1More info
- Keyword only arguments
- Positional only arguments
- /tag param-arg (Parameters vs. Arguments)
Operator precedence is essentially like an order of operations for Python's operators.
Example 1 (arithmetic)
2 * 3 + 1 is 7 because multiplication is first
2 * (3 + 1) is 8 because the parenthesis change the precedence allowing the sum to be first
Example 2 (logic)
not True or True is True because the not is first
not (True or True) is False because the or is first
The full table of precedence from lowest to highest is here
Single and Double quoted strings are the same in Python. The choice of which one to use is up to you, just make sure that you stick to that choice.
With that said, there are exceptions to this that are more important than consistency. If a single or double quote is needed inside the string, using the opposite quotation is better than using escape characters.
Example:
'My name is "Guido"'   # good
"My name is \"Guido\"" # bad
"Don't go in there"  # good
'Don\'t go in there' # badReferences:
- pep-8 on quotes
- convention for triple quoted strings
Beginners often iterate over range(len(...)) because they look like Java or C-style loops, but this is almost always a bad practice in Python.
for i in range(len(my_list)):
    do_something(my_list[i])for item in my_list:
    do_something(item)Regular expressions (regex) are a tool for finding patterns in strings. The standard library's re module defines functions for using regex patterns.
Example We can use regex to pull out all the numbers in a sentence:
>>> import re
>>> text = "On Oct 18 1963 a cat was launched aboard rocket #47"
>>> regex_pattern = r"[0-9]{1,3}"  # Matches 1-3 digits
>>> re.findall(regex_pattern, text)
['18', '196', '3', '47']  # Notice the year is cut offA relative path is a partial path that is relative to your current working directory. A common misconception is that your current working directory is the location of the module you're executing, but this is not the case. Your current working directory is actually the directory you were in when you ran the Python interpreter. The reason for this misconception is because a common way to run your code is to navigate to the directory your module is stored, and run python <module>.py. Thus, in this case your current working directory will be the same as the location of the module. However, if we instead did python path/to/<module>.py, our current working directory would no longer be the same as the location of the module we're executing.
Why is this important?
When opening files in Python, relative paths won't always work since it's dependent on what directory you were in when you ran your code. A common issue people face is running their code in an IDE thinking they can open files that are in the same directory as their module, but the current working directory will be different than what they expect and so they won't find the file. The way to avoid this problem is by using absolute paths, which is the full path from your root directory to the file you want to open.
A REPL is an interactive shell where you can execute individual lines of code one at a time, like so:
>>> x = 5
>>> x + 2
7
>>> for i in range(3):
...     print(i)
...
0
1
2
>>>python (py on Windows) in the command line without any arguments. The >>> or ... at the start of some lines are prompts to enter code, and indicate that you are in the Python REPL. Any other lines show the output of the code.
Trying to execute commands for the command-line (such as pip install xyz) in the REPL will throw an error. To run these commands, exit the REPL first by running exit() and then run the original command.
A value created inside a function can't be used outside of it unless you return it.
Consider the following function:
def square(n):
    return n * nx, we would do:
x = square(5). x would now equal 25.
Common Mistakes
>>> def square(n):
...     n * n  # calculates then throws away, returns None
...
>>> x = square(5)
>>> print(x)
None
>>> def square(n):
...     print(n * n)  # calculates and prints, then throws away and returns None
...
>>> x = square(5)
25
>>> print(x)
None-
print() and return do not accomplish the same thing. print() will show the value, and then it will be gone.- A function will return
None if it ends without a return statement.- When you want to print a value from a function, it's best to return the value and print the function call instead, like
print(square(5)).Here's a handy animation demonstrating how print and return differ in behavior.
See also: /tag return
Python 3 uses bankers' rounding (also known by other names), where if the fractional part of a number is .5, it's rounded to the nearest even result instead of away from zero.
Example:
>>> round(2.5)
2
>>> round(1.5)
2Why this is done: The round half up technique creates a slight bias towards the larger number. With a large amount of calculations, this can be significant. The round half to even technique eliminates this bias.
It should be noted that round half to even distorts the distribution by increasing the probability of evens relative to odds, however this is considered less important than the bias explained above.
References:
- Wikipedia article about rounding
- Documentation on round function
- round in what's new in python 3 (4th bullet down)
- How to force rounding technique
A scope defines the visibility of a name within a block, where a block is a piece of Python code executed as a unit. For simplicity, this would be a module, a function body, and a class definition. A name refers to text bound to an object.
For more information about names, see /tag names
A module is the source code file itself, and encompasses all blocks defined within it. Therefore if a variable is defined at the module level (top-level code block), it is a global variable and can be accessed anywhere in the module as long as the block in which it's referenced is executed after it was defined.
Alternatively if a variable is defined within a function block for example, it is a local variable. It is not accessible at the module level, as that would be outside its scope. This is the purpose of the return statement, as it hands an object back to the scope of its caller. Conversely if a function was defined inside the previously mentioned block, it would have access to that variable, because it is within the first function's scope.
>>> def outer():
...     foo = 'bar'     # local variable to outer
...     def inner():
...         print(foo)  # has access to foo from scope of outer
...     return inner    # brings inner to scope of caller
...
>>> inner = outer()  # get inner function
>>> inner()  # prints variable foo without issue
bar1. Program structure, name binding and resolution
2.
global statement3.
nonlocal statementIn the context of a file object, the seek function changes the stream position to a given byte offset, with an optional argument of where to offset from. While you can find the official documentation here, it can be unclear how to actually use this feature, so keep reading to see examples on how to use it.
File named example:
foobar
spam eggsf = open('example', 'rb')f.seek(3, 0), our stream position will move 3 bytes forward relative to the beginning of the stream. Now if we then did f.read(1) to read a single byte from where we are in the stream, it would return the string 'b' from the 'b' in 'foobar'. Notice that the 'b' is the 4th character. Also note that after we did f.read(1), we moved the stream position again 1 byte forward relative to the current position in the stream. So the stream position is now currently at position 4.
Now lets do f.seek(4, 1). This will move our stream position 4 bytes forward relative to our current position in the stream. Now if we did f.read(1), it would return the string 'p' from the 'p' in 'spam' on the next line. Note this time that the character at position 6 is the newline character '\n'.
Finally, lets do f.seek(-4, 2), moving our stream position backwards 4 bytes relative to the end of the stream. Now if we did f.read() to read everything after our position in the file, it would return the string 'eggs' and also move our stream position to the end of the file.
Note
- For the second argument in seek(), use os.SEEK_SET, os.SEEK_CUR, and os.SEEK_END in place of 0, 1, and 2 respectively.
- os.SEEK_CUR is only usable when the file is in byte mode.
When calling a method from a class instance (ie. instance.method()), the instance itself will automatically be passed as the first argument implicitly. By convention, we call this self, but it could technically be called any valid variable name.
class Foo:
    def bar(self):
        print('bar')
    def spam(self, eggs):
        print(eggs)
foo = Foo()If we call foo.bar(), it is equivalent to doing Foo.bar(foo). Our instance foo is passed for us to the bar function, so while we initially gave zero arguments, it is actually called with one.
Similarly if we call foo.spam('ham'), it is equivalent to
doing Foo.spam(foo, 'ham').
Why is this useful?
Methods do not inherently have access to attributes defined in the class. In order for any one method to be able to access other methods or variables defined in the class, it must have access to the instance.
Consider if outside the class, we tried to do this: spam(foo, 'ham'). This would give an error, because we don't have access to the spam method directly, we have to call it by doing foo.spam('ham'). This is also the case inside of the class. If we wanted to call the bar method inside the spam method, we'd have to do self.bar(), just doing bar() would give an error.
Our official website is an open-source community project created with Python and Django. It contains information about the server itself, lets you sign up for upcoming events, has its own wiki, contains a list of valuable learning resources, and much more.
Slicing is a way of accessing a part of a sequence by specifying a start, stop, and step. As with normal indexing, negative numbers can be used to count backwards.
Examples
>>> letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> letters[2:]  # from element 2 to the end
['c', 'd', 'e', 'f', 'g']
>>> letters[:4]  # up to element 4
['a', 'b', 'c', 'd']
>>> letters[3:5]  # elements 3 and 4 -- the right bound is not included
['d', 'e']
>>> letters[2:-1:2]  # Every other element between 2 and the last
['c', 'e']
>>> letters[::-1]  # The whole list in reverse
['g', 'f', 'e', 'd', 'c', 'b', 'a']
>>> words = "Hello world!"
>>> words[2:7]  # Strings are also sequences
"llo w"Don't use f-strings (f"") or other forms of "string interpolation" (%, +, .format) to inject data into a SQL query. It is an endless source of bugs and syntax errors. Additionally, in user-facing applications, it presents a major security risk via SQL injection.
Your database library should support "query parameters". A query parameter is a placeholder that you put in the SQL query. When the query is executed, you provide data to the database library, and the library inserts the data into the query for you, safely.
For example, the sqlite3 package supports using ? as a placeholder:
query = "SELECT * FROM stocks WHERE symbol = ?;"
params = ("RHAT",)
db.execute(query, params)%s and $1. Consult your library's documentation for details.
See Also - Python sqlite3 docs - How to use placeholders to bind values in SQL queries - PEP-249 - A specification of how database libraries in Python should work
Wildcard imports are import statements in the form from <module_name> import *. What imports like these do is that they import everything [1] from the module into the current module's namespace [2]. This allows you to use names defined in the imported module without prefixing the module's name.
Example:
>>> from math import *
>>> sin(pi / 2)
1.0Example:
>>> from custom_sin import sin
>>> from math import *
>>> sin(pi / 2)  # uses sin from math rather than your custom sinsin function is actually being used. From the Zen of Python [3]: Explicit is better than implicit.
- Makes import order significant, which they shouldn't. Certain IDE's sort import functionality may end up breaking code due to namespace collision.
How should you import?
- Import the module under the module's namespace (Only import the name of the module, and names defined in the module can be used by prefixing the module's name)
>>> import math >>> math.sin(math.pi / 2)
- Explicitly import certain names from the module
 Conclusion: Namespaces are one honking great idea -- let's do more of those! [3]>>> from math import sin, pi >>> sin(pi / 2)
[1] If the module defines the variable __all__, the names defined in __all__ will get imported by the wildcard import, otherwise all the names in the module get imported (except for names with a leading underscore)
[2] Namespaces and scopes
[3] Zen of Python
If you want to display a list (or some other iterable), you can write:
colors = ['red', 'green', 'blue', 'yellow']
output = ""
separator = ", "
for color in colors:
    output += color + separator
print(output)
# Prints 'red, green, blue, yellow, 'A better solution is to use str.join.
colors = ['red', 'green', 'blue', 'yellow']
separator = ", "
print(separator.join(colors))
# Prints 'red, green, blue, yellow'str.join strings. For a list of ints,
you must convert each element to a string before joining.
integers = [1, 3, 6, 10, 15]
print(", ".join(str(e) for e in integers))
# Prints '1, 3, 6, 10, 15'The String Formatting Language in Python is a powerful way to tailor the display of strings and other data structures. This string formatting mini language works for f-strings and .format().
Take a look at some of these examples!
>>> my_num = 2134234523
>>> print(f"{my_num:,}")
2,134,234,523
>>> my_smaller_num = -30.0532234
>>> print(f"{my_smaller_num:=09.2f}")
-00030.05
>>> my_str = "Center me!"
>>> print(f"{my_str:-^20}")
-----Center me!-----
>>> repr_str = "Spam \t Ham"
>>> print(f"{repr_str!r}")
'Spam \t Ham'When working with strip, lstrip, or rstrip, you might think that this would be the case:
>>> "Monty Python".rstrip(" Python")
"Monty""M"If you want to remove a prefix/suffix from a string, str.removeprefix and str.removesuffix are recommended and were added in 3.9.
>>> "Monty Python".removesuffix(" Python")
"Monty"Why Avoid System Python for Development on Unix-like Systems:
- Critical Operating System Dependencies: Altering the system Python installation may harm internal operating system dependencies.
- Stability and Security Concerns: System interpreters lag behind current releases, lacking the latest features and security patches.
- Limited Package Control: External package management restricts control over versions, leading to compatibility issues with outdated packages.
Recommended Approach:
- Install Independent Interpreter: Install Python from source or utilize a virtual environment for flexibility and control.
- Utilize Pyenv or Similar Tools: Manage multiple Python versions and create isolated development environments for smoother workflows.
The Tools page on our website contains a couple of the most popular tools for programming in Python.
Please provide the full traceback for your exception in order to help us identify your issue. While the last line of the error message tells us what kind of error you got, the full traceback will tell us which line, and other critical information to solve your problem. Please avoid screenshots so we can copy and paste parts of the message.
A full traceback could look like:
Traceback (most recent call last):
  File "my_file.py", line 5, in <module>
    add_three("6")
  File "my_file.py", line 2, in add_three
    a = num + 3
        ~~~~^~~
TypeError: can only concatenate str (not "int") to strA type hint indicates what type a variable is expected to be.
def add(a: int, b: int) -> int:
    return a + badd function the parameters a and b should be integers, and the function should return an integer when called.
It's important to note these are just hints and are not enforced at runtime.
add("hello ", "world")Third party tools like mypy can validate your code to ensure it is type hinted correctly. This can help you identify potentially buggy code, for example it would error on the second example as our add function is not intended to concatenate strings.
mypy's documentation contains useful information on type hinting, and for more information check out this documentation page.
- __name__: Used to implement special behaviour, such as the- +operator for classes with the- __add__method. More info
- _name: Indicates that a variable is "private" and should only be used by the class or module that defines it
- name_: Used to avoid naming conflicts. For example, as- classis a keyword, you could call a variable- class_instead
- __name: Causes the name to be "mangled" if defined inside a class. More info
A single underscore, _, has multiple uses:
- To indicate an unused variable, e.g. in a for loop if you don't care which iteration you are on
for _ in range(10):
    print("Hello World")_
>>> 1 + 1  # Evaluated and stored in `_`
    2
>>> _ + 3  # Take the previous result and add 3
    5x = 1_500_000 can be written instead of x = 1500000 to improve readability
See also "Reserved classes of identifiers" in the Python docs, and this more detailed guide.
Virtual environments are isolated Python environments, which make it easier to keep your system clean and manage dependencies. By default, when activated, only libraries and scripts installed in the virtual environment are accessible, preventing cross-project dependency conflicts, and allowing easy isolation of requirements.
To create a new virtual environment, you can use the standard library venv module: python3 -m venv .venv (replace python3 with python or py on Windows)
Then, to activate the new virtual environment:
Windows (PowerShell): .venv\Scripts\Activate.ps1
or (Command Prompt): .venv\Scripts\activate.bat
MacOS / Linux (Bash): source .venv/bin/activate
Packages can then be installed to the virtual environment using pip, as normal.
For more information, take a read of the documentation. If you run code through your editor, check its documentation on how to make it use your virtual environment. For example, see the VSCode or PyCharm docs.
Tools such as poetry and pipenv can manage the creation of virtual environments as well as project dependencies, making packaging and installing your project easier.
Note: When using PowerShell in Windows, you may need to change the execution policy first. This is only required once per user:
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUserCan’t talk in voice chat? Check out <#764802555427029012> to get access. The criteria for verifying are specified there.
If you have installed Python but forgot to check the Add Python to PATH option during the installation, you may still be able to access your installation with ease.
If you did not uncheck the option to install the py launcher, then you'll instead have a py command which can be used in the same way. If you want to be able to access your Python installation via the python command, then your best option is to re-install Python (remembering to tick the Add Python to PATH checkbox).
You can pass any options to the Python interpreter, e.g. to install the numpy module from PyPI you can run py -3 -m pip install numpy or python -m pip install numpy.
You can also access different versions of Python using the version flag of the py command, like so:
C:\Users\Username> py -3.7
... Python 3.7 starts ...
C:\Users\Username> py -3.6
... Python 3.6 starts ...
C:\Users\Username> py -2
... Python 2 (any version installed) starts ...The with keyword triggers a context manager. Context managers automatically set up and take down data connections, or any other kind of object that implements the magic methods __enter__ and __exit__.
with open("test.txt", "r") as file:
    do_things(file)file when the with block exits, so you never have to manually do a file.close(). Most connection types, including file readers and database connections, support this.
For more information, read the official docs, watch Corey Schafer\'s context manager video, or see PEP 343.
The XY problem can be summarised as asking about your attempted solution, rather than your actual problem.
Often programmers will get distracted with a potential solution they've come up with, and will try asking for help getting it to work. However, it's possible this solution either wouldn't work as they expect, or there's a much better solution instead.
For more information and examples, see http://xyproblem.info/.
Per Python Discord's Rule 5, we are unable to assist with questions related to youtube-dl, pytube, or other YouTube video downloaders, as their usage violates YouTube's Terms of Service.
For reference, this usage is covered by the following clauses in YouTube's TOS, as of 2021-03-17:
The following restrictions apply to your use of the Service. You are not allowed to:
1. access, reproduce, download, distribute, transmit, broadcast, display, sell, license, alter, modify or otherwise use any part of the Service or any Content except: (a) as specifically permitted by the Service;  (b) with prior written permission from YouTube and, if applicable, the respective rights holders; or (c) as permitted by applicable law;
3. access the Service using any automated means (such as robots, botnets or scrapers) except: (a) in the case of public search engines, in accordance with YouTube’s robots.txt file; (b) with YouTube’s prior written permission; or (c) as permitted by applicable law;
9. use the Service to view or listen to Content other than for personal, non-commercial use (for example, you may not publicly screen videos or stream music from the Service)The zip function allows you to iterate through multiple iterables simultaneously. It joins the iterables together, almost like a zipper, so that each new element is a tuple with one element from each iterable.
letters = 'abc'
numbers = [1, 2, 3]
# list(zip(letters, numbers)) --> [('a', 1), ('b', 2), ('c', 3)]
for letter, number in zip(letters, numbers):
    print(letter, number)zip() iterator is exhausted after the length of the shortest iterable is exceeded. If you would like to retain the other values, consider using itertools.zip_longest.
For more information on zip, please refer to the official documentation.