Week 25 - June 2023#

1. ๐Ÿ Power of the โ€œreprโ€ function in python.#

๐Ÿ Python developers, letโ€™s dive into the fascinating world of the โ€œreprโ€ function! ๐ŸŽ‰

โšก๏ธ Have you ever encountered a situation where โ€œprintโ€ gives you a different result than โ€œreprโ€? Let me show you the magic of โ€œreprโ€ in such scenarios.

๐Ÿ” Imagine you have a complex object with intricate internal state. When you use โ€œprintโ€ to display it, you might get an output that doesnโ€™t reveal the full picture. But fear not! โ€œreprโ€ comes to the rescue.

๐Ÿ’ก The โ€œreprโ€ function provides a detailed and unambiguous string representation of an object, perfect for debugging and understanding its internals.

๐ŸŒŸ Letโ€™s consider a complex example:

import datetime

now = datetime.datetime.now()

print("Printing using print:")
print(now)  # Output: 2023-06-22 15:30:45.123456

print("\nPrinting using repr:")
print(repr(now))  # Output: datetime.datetime(2023, 6, 22, 15, 30, 45, 123456)

๐Ÿ”Ž Notice the difference? While โ€œprintโ€ gives us a more human-readable representation, โ€œreprโ€ provides an exact and detailed view of the object.

๐ŸŽฏ โ€œreprโ€ is a valuable tool when debugging complex data structures or objects with custom implementations. It helps us uncover hidden details and understand the inner workings of our code.

๐Ÿ’ก So, remember to leverage the power of โ€œreprโ€ whenever you encounter complex objects that need thorough inspection!

โœจ Letโ€™s embrace โ€œreprโ€ and unlock new levels of debugging and understanding in our Python projects. Happy coding, everyone! ๐Ÿ’ป

2. ๐ŸŒˆ Enhancing console output with ANSI color codes.#

Do you want to add some pizzazz to your Python console output? ๐Ÿ’ฅ Say hello to ANSI escape codes! ๐ŸŽจโœจ

ANSI escape codes are special character sequences that allow you to change the color and formatting of text in the console or terminal. Letโ€™s take a look at how you can use them in Python to bring your console output to life! ๐Ÿš€

# ANSI color codes
RESET = "\033[0m"
RED = "\033[31m"
GREEN = "\033[32m"
YELLOW = "\033[33m"
BLUE = "\033[34m"
MAGENTA = "\033[35m"
CYAN = "\033[36m"
WHITE = "\033[37m"

# Example usage
print(RED + "This text is red." + RESET)
print(GREEN + "This text is green." + RESET)
print(YELLOW + "This text is yellow." + RESET)
print(BLUE + "This text is blue." + RESET)
print(MAGENTA + "This text is magenta." + RESET)
print(CYAN + "This text is cyan." + RESET)
print(WHITE + "This text is white." + RESET)

With just a few lines of code, you can transform your console output into a vibrant display of colors. ๐ŸŒˆโœจ Imagine the possibilities! ๐ŸŽ‰

However, keep in mind that ANSI escape codes may not work on all terminals or console emulators, especially on Windows. But donโ€™t worry, Windows users can achieve similar effects by using the colorama library. Simply install it with pip install colorama and modify the code as follows:

from colorama import Fore, Style

# Example usage
print(Fore.RED + "This text is red." + Style.RESET_ALL)
print(Fore.GREEN + "This text is green." + Style.RESET_ALL)
print(Fore.YELLOW + "This text is yellow." + Style.RESET_ALL)
print(Fore.BLUE + "This text is blue." + Style.RESET_ALL)
print(Fore.MAGENTA + "This text is magenta." + Style.RESET_ALL)
print(Fore.CYAN + "This text is cyan." + Style.RESET_ALL)
print(Fore.WHITE + "This text is white." + Style.RESET_ALL)

Now you can enjoy colorful console output on any platform! ๐ŸŽ‰๐ŸŽ‰

So go ahead and make your Python console output stand out from the crowd. Impress your colleagues and friends with eye-catching displays of information. ๐ŸŒŸโœจ

Have fun experimenting with ANSI color codes in Python, and let your imagination run wild! ๐Ÿš€๐Ÿ

3. ๐Ÿ”€ Partial method in python#

Partial methods are a fascinating feature in Python that allow you to create new methods from existing ones by pre-filling some of the arguments. This enables you to customize and specialize functions without the need for repetitive code. Letโ€™s explore this concept further! ๐Ÿ’ก๐Ÿ”ง

Imagine you have a function with multiple arguments, and you frequently call it with some fixed values for some of the parameters. Instead of passing those values every time you call the function, you can use partial methods to create a new function with those arguments already filled in. This can make your code more concise and easier to read. ๐Ÿงฉโœจ

In Python, you can utilize the functools module to create partial methods. The functools module provides the partial function, which takes a callable and any number of arguments or keyword arguments. It returns a new partial object, which can be called as a regular function. ๐Ÿ’ป๐Ÿ”

Hereโ€™s an example to illustrate the concept: ๐Ÿ“

from functools import partial

def greet(name, greeting):
    print(f"{greeting}, {name}!")

say_hello = partial(greet, greeting="Hello")
say_hello("Alice")  # Output: Hello, Alice!
say_hello("Bob")    # Output: Hello, Bob!

In the example above, we defined a greet function that takes two arguments: name and greeting. By using partial, we created a new function called say_hello, where the greeting argument is already set to โ€œHelloโ€. Now, whenever we call say_hello, we only need to provide the name argument. ๐Ÿ‘‹๐Ÿ‘‹

Partial methods are particularly useful when working with libraries or frameworks that require callback functions with predefined arguments. Instead of writing separate functions for each callback, you can use partial methods to create specialized callbacks without duplicating code. ๐Ÿ“š๐Ÿงช

Remember that partial methods are not limited to positional arguments only; you can also use them with keyword arguments. Additionally, you can modify or override any of the pre-filled arguments when calling the partial method, providing you with even more flexibility. ๐ŸŽ›๏ธ๐Ÿ”€

4. ๐Ÿ”‘ Encoding and Decoding using Base64#

Base64 encoding is commonly used when you need to represent binary data, such as images or files, as ASCII text. It converts binary data into a string of characters that are safe to transmit or store, ensuring compatibility across different systems and protocols. Python provides a convenient way to perform base64 encoding and decoding using the built-in base64 module. ๐Ÿ“š๐Ÿ”ก

Letโ€™s take a look at an example to see how base64 encoding and decoding work: ๐Ÿ–ฅ๏ธ๐Ÿ”‘

import base64

# Encoding binary data to base64
data = b"Python-World"
encoded_data = base64.b64encode(data)
print(encoded_data)  # Output: b'UHl0aG9uLVdvcmxk'

# Decoding base64 data to binary
decoded_data = base64.b64decode(encoded_data)
print(decoded_data)  # Output: b'Python-World'

In the example above, we imported the base64 module and encoded the binary data โ€œPython-Worldโ€ using base64.b64encode(). The result, encoded_data, is a byte string representing the base64 encoded version of the data. When printing encoded_data, the b prefix indicates that it is a byte string. ๐Ÿ“œ๐Ÿ”ข

To decode the base64 data back into its original binary form, we used base64.b64decode() and assigned the result to decoded_data. Printing decoded_data shows that it successfully restored the original binary data. ๐Ÿ”„๐Ÿ”ค

Base64 encoding and decoding have various applications, including data transmission over email, storage of binary data in JSON or XML formats, and handling binary data in network protocols. Understanding base64 encoding is essential when working with data that needs to be safely represented as text. ๐Ÿ“ก๐Ÿ“ฆ

Pythonโ€™s base64 module provides additional functionalities, such as handling URL-safe base64 encoding and decoding, as well as encoding and decoding using different character sets. Exploring these options can further enhance your encoding and decoding capabilities. ๐ŸŒ๐Ÿ” 

5. ๐ŸŽฃ Understanding hooks in requests#

Hooks in the requests module provide a mechanism to intercept and modify the request and response flow. They enable you to inject your own code at various stages of the request lifecycle, empowering you to perform custom processing, logging, authentication, error handling, and much more. Hooks are a powerful tool to enhance and tailor your HTTP requests according to your specific needs. ๐Ÿ’ก๐Ÿ”Œ

Types of Hooks:

  1. Response Hooks:

    • response: Executed after a response is received, regardless of the response status.

These hooks provide immense flexibility and control over your requests, enabling you to customize and augment the behavior as per your requirements. โš™๏ธ๐ŸŽ›๏ธ

๐ŸŽฏ Use Cases for Hooks:

Hooks can be employed in various scenarios to enhance the functionality of your requests. Some common use cases include:

  1. Logging: Add logging statements to track the request and response details for debugging or analysis purposes.

  2. Authentication: Implement custom authentication mechanisms or token management.

  3. Error Handling: Define actions to be taken when specific exceptions occur during the request.

  4. Retry Strategies: Implement custom retry logic based on response status codes or error conditions.

๐ŸŒŸ Registering Hooks with Specific Requests:

In addition to registering global hooks, you can also specify hooks as keyword parameters when making individual requests using methods like get, post, put, etc. This allows you to define hooks specifically for a particular request and control their execution on a per-request basis. Hereโ€™s an example:

import requests

def first_hook(response, *args, **kwargs):
    # Perform custom logic for the first hook
    print("First hook executed")
    response.first_hook='you can pass any value or object'

def second_hook(response, *args, **kwargs):
    # Perform custom logic for the second hook
    print("Second hook executed")

# Make a request with multiple hooks
response = requests.get('https://www.example.com', hooks={'response': [first_hook, second_hook]})

# Retrive first_hook parameters
print(response.first_hook)

In this case, both first_hook and second_hook will be executed for the single request made in the get method.

๐Ÿš€ Registering Hooks with a Session:

If you need to maintain state or persist hooks across multiple requests, you can use a requests.Session object. Hereโ€™s an example:

import requests

def custom_hook(response, *args, **kwargs):
    # Perform custom logic
    print("Custom hook executed")

    # Also U can set custom attibute to response object
    response.custom_hook_called=True


# Create a session and register the custom hook
session = requests.Session()
session.hooks['response'].append(custom_hook)

# Make requests using the session
response1 = session.get('https://www.example.com')

## Status of custom hooks
print("parameter from custom hooks:",response1.custom_hook_called)

In this example, the custom_hook will be executed for both response1 and response2, as they are made using the same session.

6. ๐Ÿ“ข LinkExtractor in Scrapy#

๐Ÿ”— The LinkExtractor class in Scrapy is a powerful tool for extracting links from web pages. It provides a convenient way to crawl and scrape websites efficiently. Letโ€™s dive into some simple code examples to understand how it works.

๐Ÿ“ Code Example:

import scrapy
from scrapy.crawler import CrawlerProcess
from scrapy.linkextractors import LinkExtractor

class MySpider(scrapy.Spider):
    name = 'example'
    start_urls = ['http://www.example.com']

    def parse(self, response):
        # Instantiate a LinkExtractor object
        link_extractor = LinkExtractor()

        # Extract links from the response
        links = link_extractor.extract_links(response)

        # Process the extracted links
        for link in links:
            # Access the URL, text, and other attributes of the link
            yield {
                'url': link.url,
                'text': link.text
            }



# Create a CrawlerProcess instance
process = CrawlerProcess()

# Add your spider to the CrawlerProcess
process.crawl(MySpider)

# Start the crawling process
process.start()


# Output: > {'url': 'https://www.iana.org/domains/example', 'text': 'More information...'}

๐Ÿ” In this example, we create a Scrapy spider named MySpider. The LinkExtractor class is imported from scrapy.linkextractors to handle link extraction.

๐Ÿ•ธ๏ธ Inside the parse method, we instantiate a LinkExtractor object. Then, we use the extract_links method to extract all links from the response object.

๐Ÿ”— We iterate over the extracted links and access their URL and text using the url and text attributes. You can perform further processing or extraction based on your specific needs.

๐Ÿ“ฅ Finally, we yield a dictionary containing the URL and text of each extracted link. You can modify this code to process the links differently or store them in any desired format.

๐Ÿ’ก The LinkExtractor class provides many additional options and parameters to customize link extraction based on patterns, tags, attributes, and more. Make sure to explore the Scrapy documentation for more advanced usage.

7. ๐Ÿ“ itemgetter in python#

๐Ÿ” The itemgetter function in Python is a convenient tool for extracting specific elements from iterable objects. It provides a simple and efficient way to access and manipulate data. Letโ€™s explore its functionality with some simple code examples, including its usage in sorted with lists, dictionaries, and lists of dictionaries.

In general, if you need to access specific elements from iterable objects and performance is a concern, using itemgetter is a recommended approach. It offers better performance compared to using a lambda function, particularly when dealing with large datasets or performing operations that need to be executed multiple times.

๐Ÿ“ Code Example:

from operator import itemgetter

# Example 1: Accessing Elements from a List
my_list = ['apple', 'banana', 'cherry', 'date']
get_second_element = itemgetter(1)
print(get_second_element(my_list))  # Output: 'banana'

# Example 2: Accessing Elements from a Dictionary
my_dict = {'name': 'John', 'age': 30, 'city': 'New York'}
get_age = itemgetter('age')
print(get_age(my_dict))  # Output: 30

# Example 3: Accessing Multiple Elements from a Tuple
my_tuple = ('apple', 'banana', 'cherry', 'date')
get_first_and_last = itemgetter(0, -1)
print(get_first_and_last(my_tuple))  # Output: ('apple', 'date')

# Example 4: Using itemgetter in sorted with a List of Tuples
students = [('John', 20, 'A'),('Alice', 19, 'B'),('Bob', 21, 'A-'),('Carol', 18, 'B+')]
sorted_students = sorted(students, key=itemgetter(2))
print(sorted_students)

# Example 5: Using itemgetter in sorted with a Dictionary
student_grades = {'John': 'A','Alice': 'B','Bob': 'A-','Carol': 'B+'}
sorted_grades = sorted(student_grades.items(), key=itemgetter(1))
print(sorted_grades)

# Example 6: Using itemgetter in sorted with a List of Dictionaries
people = [
    {'name': 'John', 'age': 25},
    {'name': 'Alice', 'age': 30},
    {'name': 'Bob', 'age': 20},
    {'name': 'Carol', 'age': 35}
]
sorted_people = sorted(people, key=itemgetter('age'))
print(sorted_people)

๐Ÿ”ข In these examples, we import the itemgetter function from the operator module to extract specific elements from iterable objects.

๐Ÿ“Œ Examples 1, 2, and 3 demonstrate how itemgetter can be used to access elements from a list, dictionary, and tuple, respectively.

๐Ÿ“Œ Example 4 showcases the usage of itemgetter in the sorted function with a list of tuples. By specifying key=itemgetter(2), the sorted function sorts the students based on their grade (the third element in each tuple).

๐Ÿ“Œ Example 5 illustrates how itemgetter can be used with the sorted function with a dictionary. We convert the dictionary items into a list of tuples using the items() method and then sort the tuples based on the grades using key=itemgetter(1).

๐Ÿ“Œ Example 6 demonstrates the usage of itemgetter in the sorted function with a list of dictionaries. By specifying key=itemgetter('age'), the sorted function sorts the list of dictionaries based on the โ€˜ageโ€™ key, resulting in a sorted list of

people based on their age.

๐Ÿ’ก The itemgetter function is a powerful tool for accessing and sorting specific elements from iterable objects. It offers flexibility and performance benefits, making it a valuable addition to your Python toolkit.

8. ๐Ÿ–ฅ๏ธ Fetching device name using platform#

๐Ÿ” The platform module in Python provides a convenient way to access information about the platform your code is running on. Letโ€™s dive into how you can use this module to fetch the device name:

๐Ÿ”ฆ Fetching Device Name: The platform moduleโ€™s node() function returns the deviceโ€™s network name, which is often the deviceโ€™s hostname. This can provide a reasonable approximation of the device name in many cases.

import platform

device_name = platform.node()
print(f"Device Name: {device_name}")

๐Ÿ–ฅ๏ธ๐Ÿ’ป๐Ÿ“ฑ The device_name variable will contain the name of the device your code is running on, which could be the hostname of the machine or a recognizable identifier for the device.

๐Ÿš€ Platform Information: The platform module can provide more than just the device name. You can also access other platform-related information, such as the operating system, Python implementation, and architecture.

import platform

# Get the operating system name
os_name = platform.system()
print(f"Operating System: {os_name}")

# Get the release version of the operating system
os_release = platform.release()
print(f"Release Version: {os_release}")

# Get the version of the operating system
os_version = platform.version()
print(f"OS Version: {os_version}")

# Get the machine type
machine_type = platform.machine()
print(f"Machine Type: {machine_type}")

# Get the processor name or identifier
processor = platform.processor()
print(f"Processor: {processor}")

# Get the version of Python
python_version = platform.python_version()
print(f"Python Version: {python_version}")

# Get the name of the Python implementation
python_implementation = platform.python_implementation()
print(f"Python Implementation: {python_implementation}")

# Get the compiler used to build Python
python_compiler = platform.python_compiler()
print(f"Python Compiler: {python_compiler}")

# Get the architecture and bitness of the operating system
architecture, bitness = platform.architecture()
print(f"Architecture: {architecture}")
print(f"Bitness: {bitness}")

# Get the network name of the device
device_name = platform.node()
print(f"Device Name: {device_name}")

'''
Output:
Operating System: Windows
Release Version: 11
OS Version: 12.0.22334621
Machine Type: AMD64
Processor: AMD64 Family 21 Model 111 Stepping 2, AuthenticAMD
Python Version: 3.11.3
Python Implementation: CPython
Python Compiler: MSC v.1934 64 bit (AMD64)
Architecture: 64bit
Bitness: WindowsPE
Device Name: DESKTOP-KJK
'''

๐Ÿ“ก Platform-Specific Functionality: By knowing the device name or platform, you can tailor your codeโ€™s behavior to provide platform-specific functionality. For example, you can enable or disable certain features, adjust settings, or optimize code paths based on the device or platform your code is running on.

๐Ÿ’ก Fetching the device name using the platform module allows you to adapt your code to different devices and platforms. It opens up possibilities for building cross-platform applications, device-specific optimizations, and customized user experiences.

9. ๐ŸŒŸ Package your app into a executable file using zipapp#

๐Ÿ” What is Zipapp? Zipapp is a module introduced in Python 3.5 that enables you to package your Python application along with its dependencies into a single executable ZIP file. This ZIP file can be executed directly, making it convenient to distribute your application as a standalone package.

๐Ÿš€ Key Features and Benefits:

  • Simplified Distribution:

    With Zipapp, you can distribute your Python application as a single file, eliminating the need for users to install dependencies separately.

  • Easy Execution:

    The executable ZIP file can be run directly without the need for a Python interpreter or additional setup.

  • Cross-Platform Compatibility:

    Zipapp packages are portable and can be executed on different operating systems, making it easier to distribute your application across platforms.

๐Ÿ”ง Creating a Zipapp:

Creating a zipapp is straightforward.Hereโ€™s a simple example create app.py file in myapp:

# myapp/app.py
def main():
    print("Hello, Python-World!")

if __name__ == '__main__':
    main()

To create the zipapp

python -m zipapp myapp -m "app:main"

In this example, weโ€™re creating a zipapp named myapp.pyz, specifying the app.py file as the entry point .

๐Ÿš€ Executing the Zipapp:

Once you have the zipapp file, you can run it like any other executable. Hereโ€™s an example:

$ python myapp.pyz
Hello, Python-World!

๐Ÿ’ก Use Cases and Considerations:

  • Distribution of Command-Line Tools:

    Zipapp is an excellent choice for packaging and distributing command-line tools written in Python.

  • Portable Applications:

    If you want to create a portable Python application that can be run on different systems without requiring installation, zipapp can be a great solution.

  • Version Management:

    Zipapp can help in managing and distributing specific versions of your application, ensuring consistent execution across environments.

Zipapp is a powerful tool for simplifying the distribution and execution of your Python applications. It provides a convenient way to package your code and dependencies into a single executable file, making it easier for users to run your application without complex setup processes.

10. ๐Ÿ”ง Secure User Input with getpass()#

๐Ÿ”Ž When it comes to handling sensitive user input, such as passwords or other confidential information, security is of utmost importance.the getpass() method, which provides a secure way to accept user input without displaying it on the screen.

What is getpass()?

The getpass() method is a part of the Python getpass module. It is used to prompt the user for input, such as a password, and securely captures the input without echoing it back to the screen.

๐Ÿš€ Key Features and Benefits:

  • Secure User Input: The getpass() method ensures that sensitive user input, like passwords, remains hidden, reducing the risk of unauthorized access.

  • Cross-Platform Compatibility: The method works consistently across different operating systems, providing a reliable solution for secure user input.

  • Simplicity of Use: With a single function call, you can prompt the user for input and retrieve it securely, without the need for complex code.

๐Ÿ”ง Using getpass():

Using the getpass() method is straightforward. Hereโ€™s a simple example:

import getpass

password = getpass.getpass("Enter your password: ")
print("Password entered:", password)

When you run this code, the getpass() method will prompt the user to enter a password, and the input will be securely captured without being displayed on the screen.

๐Ÿ’ก Best Practices:

  • Avoid Storing Passwords in Plain Text: Remember, the getpass() method only helps in securely capturing user input. Itโ€™s essential to handle the captured passwords carefully and avoid storing them in plain text. Consider using secure password storage mechanisms like hashing and salting.

  • Ensure Proper Error Handling: Handle exceptions raised by the getpass() method to provide meaningful error messages and gracefully handle any issues encountered during user input.

The getpass() method is a valuable tool for securely capturing sensitive user input, making it an ideal choice when handling passwords or other confidential information. By using this method, you can enhance the security of your applications and protect user privacy.

Useful Resources#

Here are some valuable resources to enhance your Python programming skills and stay updated with the latest trends:

  • Online Course: Take your Python web development skills to the next level with the โ€œMastering Flaskโ€ course on Pluralsight.

  • Forum: Join the vibrant Python community discussions and seek help at Python Forums. Engage with fellow developers, share knowledge, and contribute to the Python ecosystem.

Stay curious, keep learning, and make the most of these resources to enhance your Python journey!