Gordon  Taylor

Gordon Taylor

1624969920

How Javascript Is Single Threaded? in-Depth Explaination Of Event Loop and Call Stacks

I started learning Javascript about 2 years ago and wondering to find bits and pieces to explore how it internally works. I’d gotta heard words like v8 runtime engine which runs on browser but didn’t know anything about it and started doing my own research and experiment in the browser. Mostly all JS dev might have heard the term V8, chrome’s Runtime but some might even didn’t really know what that meant, what that did.

First of all, what is Javascript under the hood — the core component of NodeJS. Well, JS is single threaded, single concurrent language which has a call stack, an event loop, a callback queue and some other APIs. If we talk about the v8 runtime in the browser, the below one is simplified view of what it really is…

What is call stack?

You can think call stack to be a functional stack or execution stack when your Javascript code is run line by line. Unless the part of code is handed over to the callback queue, it fills the call stack of a run-time engine.

Consider the following image for the sake of understanding.

Here, first of all JS is designed to be run on the main() thread and so the main() function will be called first when we execute the above code all together. The entry execution point is console.log() statement and the execution will be halted until the argument provided inside does not finish its execution i.e. bar(6). Now, the bar(6) will be pushed on to the stack and then it calls the function foo(3*6) and hence comes on top. Now, when the execution of foo() finishes, it will return the result by popping the entry from stack and comes down to bar(6) which in turn will return entry to the console and it prints the result.

#javascript #event-loop #call-stack #web-development

What is GEEK

Buddha Community

How Javascript Is Single Threaded? in-Depth Explaination Of Event Loop and Call Stacks

Pyringe: Debugger Capable Of Attaching to & Injecting Code Into Python

DISCLAIMER: This is not an official google project, this is just something I wrote while at Google.

Pyringe

What this is

Pyringe is a python debugger capable of attaching to running processes, inspecting their state and even of injecting python code into them while they're running. With pyringe, you can list threads, get tracebacks, inspect locals/globals/builtins of running functions, all without having to prepare your program for it.

What this is not

A "Google project". It's my internship project that got open-sourced. Sorry for the confusion.

What do I need?

Pyringe internally uses gdb to do a lot of its heavy lifting, so you will need a fairly recent build of gdb (version 7.4 onwards, and only if gdb was configured with --with-python). You will also need the symbols for whatever build of python you're running.
On Fedora, the package you're looking for is python-debuginfo, on Debian it's called python2.7-dbg (adjust according to version). Arch Linux users: see issue #5, Ubuntu users can only debug the python-dbg binary (see issue #19).
Having Colorama will get you output in boldface, but it's optional.

How do I get it?

Get it from the Github repo, PyPI, or via pip (pip install pyringe).

Is this Python3-friendly?

Short answer: No, sorry. Long answer:
There's three potentially different versions of python in play here:

  1. The version running pyringe
  2. The version being debugged
  3. The version of libpythonXX.so your build of gdb was linked against

2 Is currently the dealbreaker here. Cpython has changed a bit in the meantime[1], and making all features work while debugging python3 will have to take a back seat for now until the more glaring issues have been taken care of.
As for 1 and 3, the 2to3 tool may be able to handle it automatically. But then, as long as 2 hasn't been taken care of, this isn't really a use case in the first place.

[1] - For example, pendingbusy (which is used for injection) has been renamed to busy and been given a function-local scope, making it harder to interact with via gdb.

Will this work with PyPy?

Unfortunately, no. Since this makes use of some CPython internals and implementation details, only CPython is supported. If you don't know what PyPy or CPython are, you'll probably be fine.

Why not PDB?

PDB is great. Use it where applicable! But sometimes it isn't.
Like when python itself crashes, gets stuck in some C extension, or you want to inspect data without stopping a program. In such cases, PDB (and all other debuggers that run within the interpreter itself) are next to useless, and without pyringe you'd be left with having to debug using print statements. Pyringe is just quite convenient in these cases.

I injected a change to a local var into a function and it's not showing up!

This is a known limitation. Things like inject('var = 2') won't work, but inject('var[1] = 1337') should. This is because most of the time, python internally uses a fast path for looking up local variables that doesn't actually perform the dictionary lookup in locals(). In general, code you inject into processes with pyringe is very different from a normal python function call.

How do I use it?

You can start the debugger by executing python -m pyringe. Alternatively:

import pyringe
pyringe.interact()

If that reminds you of the code module, good; this is intentional.
After starting the debugger, you'll be greeted by what behaves almost like a regular python REPL.
Try the following:

==> pid:[None] #threads:[0] current thread:[None]
>>> help()
Available commands:
 attach: Attach to the process with the given pid.
 bt: Get a backtrace of the current position.
 [...]
==> pid:[None] #threads:[0] current thread:[None]
>>> attach(12679)
==> pid:[12679] #threads:[11] current thread:[140108099462912]
>>> threads()
[140108099462912, 140108107855616, 140108116248323, 140108124641024, 140108133033728, 140108224739072, 140108233131776, 140108141426432, 140108241524480, 140108249917184, 140108269324032]

The IDs you see here correspond to what threading.current_thread().ident would tell you.
All debugger functions are just regular python functions that have been exposed to the REPL, so you can do things like the following.

==> pid:[12679] #threads:[11] current thread:[140108099462912]
>>> for tid in threads():
...   if not tid % 10:
...     thread(tid)
...     bt()
... 
Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 524, in __bootstrap
    self.__bootstrap_inner()
  File "/usr/lib/python2.7/threading.py", line 551, in __bootstrap_inner
    self.run()
  File "/usr/lib/python2.7/threading.py", line 504, in run
    self.__target(*self.__args, **self.__kwargs)
  File "./test.py", line 46, in Idle
    Thread_2_Func(1)
  File "./test.py", line 40, in Wait
    time.sleep(n)
==> pid:[12679] #threads:[11] current thread:[140108241524480]
>>> 

You can access the inferior's locals and inspect them like so:

==> pid:[12679] #threads:[11] current thread:[140108241524480]
>>> inflocals()
{'a': <proxy of A object at remote 0x1d9b290>, 'LOL': 'success!', 'b': <proxy of B object at remote 0x1d988c0>, 'n': 1}
==> pid:[12679] #threads:[11] current thread:[140108241524480]
>>> p('a')
<proxy of A object at remote 0x1d9b290>
==> pid:[12679] #threads:[11] current thread:[140108241524480]
>>> p('a').attr
'Some_magic_string'
==> pid:[12679] #threads:[11] current thread:[140108241524480]
>>> 

And sure enough, the definition of a's class reads:

class Example(object):
  cl_attr = False
  def __init__(self):
    self.attr = 'Some_magic_string'

There's limits to how far this proxying of objects goes, and everything that isn't trivial data will show up as strings (like '<function at remote 0x1d957d0>').
You can inject python code into running programs. Of course, there are caveats but... see for yourself:

==> pid:[12679] #threads:[11] current thread:[140108241524480]
>>> inject('import threading')
==> pid:[12679] #threads:[11] current thread:[140108241524480]
>>> inject('print threading.current_thread().ident')
==> pid:[12679] #threads:[11] current thread:[140108241524480]
>>> 

The output of my program in this case reads:

140108241524480

If you need additional pointers, just try using python's help (pyhelp() in the debugger) on debugger commands.

Author: google
Source Code: https://github.com/google/pyringe
License: Apache-2.0 License

#python 

Gordon  Taylor

Gordon Taylor

1624969920

How Javascript Is Single Threaded? in-Depth Explaination Of Event Loop and Call Stacks

I started learning Javascript about 2 years ago and wondering to find bits and pieces to explore how it internally works. I’d gotta heard words like v8 runtime engine which runs on browser but didn’t know anything about it and started doing my own research and experiment in the browser. Mostly all JS dev might have heard the term V8, chrome’s Runtime but some might even didn’t really know what that meant, what that did.

First of all, what is Javascript under the hood — the core component of NodeJS. Well, JS is single threaded, single concurrent language which has a call stack, an event loop, a callback queue and some other APIs. If we talk about the v8 runtime in the browser, the below one is simplified view of what it really is…

What is call stack?

You can think call stack to be a functional stack or execution stack when your Javascript code is run line by line. Unless the part of code is handed over to the callback queue, it fills the call stack of a run-time engine.

Consider the following image for the sake of understanding.

Here, first of all JS is designed to be run on the main() thread and so the main() function will be called first when we execute the above code all together. The entry execution point is console.log() statement and the execution will be halted until the argument provided inside does not finish its execution i.e. bar(6). Now, the bar(6) will be pushed on to the stack and then it calls the function foo(3*6) and hence comes on top. Now, when the execution of foo() finishes, it will return the result by popping the entry from stack and comes down to bar(6) which in turn will return entry to the console and it prints the result.

#javascript #event-loop #call-stack #web-development

Libraries for Debugging Code in Popular Python

In this Python article, let's learn about Debugging Tools: Libraries for Debugging Code in Popular Python

Table of contents:

  • pdb-like Debugger
    • ipdb - IPython-enabled pdb.
    • pdb++ - Another drop-in replacement for pdb.
    • pudb - A full-screen, console-based Python debugger.
    • wdb - An improbable web debugger through WebSockets.
  • Tracing
    • lptrace - strace for Python programs.
    • manhole - Debugging UNIX socket connections and present the stacktraces for all threads and an interactive prompt.
    • pyringe - Debugger capable of attaching to and injecting code into Python processes.
    • python-hunter - A flexible code tracing toolkit.
  • Profiler
    • line_profiler - Line-by-line profiling.
    • memory_profiler - Monitor Memory usage of Python code.
    • py-spy - A sampling profiler for Python programs. Written in Rust.
    • pyflame - A ptracing profiler For Python.
    • vprof - Visual Python profiler.
  • Others
    • django-debug-toolbar - Display various debug information for Django.
    • django-devserver - A drop-in replacement for Django's runserver.
    • flask-debugtoolbar - A port of the django-debug-toolbar to flask.
    • icecream - Inspect variables, expressions, and program execution with a single, simple function call.
    • pyelftools - Parsing and analyzing ELF files and DWARF debugging information.

 

What is a debugging tool?

A debugger is a software tool that can help the software development process by identifying coding errors at various stages of the operating system or application development. Some debuggers will analyze a test run to see what lines of code were not executed.

Debugger for Python programs with a graphical user interface. It uses bdb (part of stdlib) but adds a GUI and has some powerful features like object browser, windows for variables, classes, functions, exceptions, stack, conditional breakpoints, etc.


Libraries for Debugging Code in Popular Python

  1. IPython pdb

ipdb exports functions to access the IPython debugger, which features tab completion, syntax highlighting, better tracebacks, better introspection with the same interface as the pdb module.

Example usage:

import ipdb
ipdb.set_trace()
ipdb.set_trace(context=5)  # will show five lines of code
                           # instead of the default three lines
                           # or you can set it via IPDB_CONTEXT_SIZE env variable
                           # or setup.cfg file
ipdb.pm()
ipdb.run('x[0] = 3')
result = ipdb.runcall(function, arg0, arg1, kwarg='foo')
result = ipdb.runeval('f(1,2) - 3')

Arguments for set_trace

The set_trace function accepts context which will show as many lines of code as defined, and cond, which accepts boolean values (such as abc == 17) and will start ipdb's interface whenever cond equals to True.

Using configuration file

It's possible to set up context using a .ipdb file on your home folder, setup.cfg or pyproject.toml on your project folder. You can also set your file location via env var $IPDB_CONFIG. Your environment variable has priority over the home configuration file, which in turn has priority over the setup config file. Currently, only context setting is available.

A valid setup.cfg is as follows

[ipdb]
context=5

A valid .ipdb is as follows

context=5

A valid pyproject.toml is as follows

[tool.ipdb]
context=5

The post-mortem function, ipdb.pm(), is equivalent to the magic function %debug.

View on GitHub


2.  pdb++

pdb++, a drop-in replacement for pdb (the Python debugger)

What is it?

This module is an extension of the pdb module of the standard library. It is meant to be fully compatible with its predecessor, yet it introduces a number of new features to make your debugging experience as nice as possible.

https://user-images.githubusercontent.com/412005/64484794-2f373380-d20f-11e9-9f04-e1dabf113c6f.png

pdb++ features include:

  • colorful TAB completion of Python expressions (through fancycompleter)
  • optional syntax highlighting of code listings (through Pygments)
  • sticky mode
  • several new commands to be used from the interactive (Pdb++) prompt
  • smart command parsing (hint: have you ever typed r or c at the prompt to print the value of some variable?)
  • additional convenience functions in the pdb module, to be used from your program

pdb++ is meant to be a drop-in replacement for pdb. If you find some unexpected behavior, please report it as a bug.

Installation

Since pdb++ is not a valid package name the package is named pdbpp:

$ pip install pdbpp

pdb++ is also available via conda:

$ conda install -c conda-forge pdbpp

Alternatively, you can just put pdb.py somewhere inside your PYTHONPATH.

View on GitHub


3.  PuDB

Its goal is to provide all the niceties of modern GUI-based debuggers in a more lightweight and keyboard-friendly package. PuDB allows you to debug code right where you write and test it--in a terminal.

Here are some screenshots:

Light theme

  • doc/images/pudb-screenshot-light.png

Dark theme

  • doc/images/pudb-screenshot-dark.png

View on GitHub


4.  wdb

An improbable web debugger through WebSockets

wdb is a full featured web debugger based on a client-server architecture.

The wdb server which is responsible of managing debugging instances along with browser connections (through websockets) is based on Tornado. The wdb clients allow step by step debugging, in-program python code execution, code edition (based on CodeMirror) setting breakpoints...

Due to this architecture, all of this is fully compatible with multithread and multiprocess programs.

wdb works with python 2 (2.6, 2.7), python 3 (3.2, 3.3, 3.4, 3.5) and pypy. Even better, it is possible to debug a python 2 program with a wdb server running on python 3 and vice-versa or debug a program running on a computer with a debugging server running on another computer inside a web page on a third computer!

Even betterer, it is now possible to pause a currently running python process/thread using code injection from the web interface. (This requires gdb and ptrace enabled)

In other words it's a very enhanced version of pdb directly in your browser with nice features.

Installation:

Global installation:

    $ pip install wdb.server

In virtualenv or with a different python installation:

    $ pip install wdb

(You must have the server installed and running)

View on GitHub


5.  lptrace

lptrace is strace for Python programs. It lets you see in real-time what functions a Python program is running. It's particularly useful to debug weird issues on production.

For example, let's debug a non-trivial program, the Python SimpleHTTPServer. First, let's run the server:

vagrant@precise32:/vagrant$ python -m SimpleHTTPServer 8080 &
[1] 1818
vagrant@precise32:/vagrant$ Serving HTTP on 0.0.0.0 port 8080 ...

Now let's connect lptrace to it:

vagrant@precise32:/vagrant$ sudo python lptrace -p 1818
...
fileno (/usr/lib/python2.7/SocketServer.py:438)
meth (/usr/lib/python2.7/socket.py:223)

fileno (/usr/lib/python2.7/SocketServer.py:438)
meth (/usr/lib/python2.7/socket.py:223)

_handle_request_noblock (/usr/lib/python2.7/SocketServer.py:271)
get_request (/usr/lib/python2.7/SocketServer.py:446)
accept (/usr/lib/python2.7/socket.py:201)
__init__ (/usr/lib/python2.7/socket.py:185)
verify_request (/usr/lib/python2.7/SocketServer.py:296)
process_request (/usr/lib/python2.7/SocketServer.py:304)
finish_request (/usr/lib/python2.7/SocketServer.py:321)
__init__ (/usr/lib/python2.7/SocketServer.py:632)
setup (/usr/lib/python2.7/SocketServer.py:681)
makefile (/usr/lib/python2.7/socket.py:212)
__init__ (/usr/lib/python2.7/socket.py:246)
makefile (/usr/lib/python2.7/socket.py:212)
__init__ (/usr/lib/python2.7/socket.py:246)
handle (/usr/lib/python2.7/BaseHTTPServer.py:336)
handle_one_request (/usr/lib/python2.7/BaseHTTPServer.py:301)
^CReceived Ctrl-C, quitting
vagrant@precise32:/vagrant$

You can see that the server is handling the request in real time! After pressing Ctrl-C, the trace is removed and the program execution resumes normally.

View on GitHub


6.  python-manhole

Debugging manhole for python applications.

Manhole is in-process service that will accept unix domain socket connections and present the stacktraces for all threads and an interactive prompt. It can either work as a python daemon thread waiting for connections at all times or a signal handler (stopping your application and waiting for a connection).

Access to the socket is restricted to the application's effective user id or root.

This is just like Twisted's manhole. It's simpler (no dependencies), it only runs on Unix domain sockets (in contrast to Twisted's manhole which can run on telnet or ssh) and it integrates well with various types of applications.

Usage

Install it:

pip install manhole

You can put this in your django settings, wsgi app file, some module that's always imported early etc:

import manhole
manhole.install() # this will start the daemon thread

# and now you start your app, eg: server.serve_forever()

Now in a shell you can do either of these:

netcat -U /tmp/manhole-1234
socat - unix-connect:/tmp/manhole-1234
socat readline unix-connect:/tmp/manhole-1234

Socat with readline is best (history, editing etc). If your socat doesn't have readline try this.

Sample output:

$ nc -U /tmp/manhole-1234

Python 2.7.3 (default, Apr 10 2013, 06:20:15)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> dir()
['__builtins__', 'dump_stacktraces', 'os', 'socket', 'sys', 'traceback']
>>> print 'foobar'
foobar

View on GitHub


7.  Pyringe

Pyringe is a python debugger capable of attaching to running processes, inspecting their state and even of injecting python code into them while they're running. With pyringe, you can list threads, get tracebacks, inspect locals/globals/builtins of running functions, all without having to prepare your program for it.

How do I use it?

You can start the debugger by executing python -m pyringe. Alternatively:

import pyringe
pyringe.interact()

If that reminds you of the code module, good; this is intentional.
After starting the debugger, you'll be greeted by what behaves almost like a regular python REPL.
Try the following:

==> pid:[None] #threads:[0] current thread:[None]
>>> help()
Available commands:
 attach: Attach to the process with the given pid.
 bt: Get a backtrace of the current position.
 [...]
==> pid:[None] #threads:[0] current thread:[None]
>>> attach(12679)
==> pid:[12679] #threads:[11] current thread:[140108099462912]
>>> threads()
[140108099462912, 140108107855616, 140108116248323, 140108124641024, 140108133033728, 140108224739072, 140108233131776, 140108141426432, 140108241524480, 140108249917184, 140108269324032]

The IDs you see here correspond to what threading.current_thread().ident would tell you.
All debugger functions are just regular python functions that have been exposed to the REPL, so you can do things like the following.

==> pid:[12679] #threads:[11] current thread:[140108099462912]
>>> for tid in threads():
...   if not tid % 10:
...     thread(tid)
...     bt()
... 
Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 524, in __bootstrap
    self.__bootstrap_inner()
  File "/usr/lib/python2.7/threading.py", line 551, in __bootstrap_inner
    self.run()
  File "/usr/lib/python2.7/threading.py", line 504, in run
    self.__target(*self.__args, **self.__kwargs)
  File "./test.py", line 46, in Idle
    Thread_2_Func(1)
  File "./test.py", line 40, in Wait
    time.sleep(n)
==> pid:[12679] #threads:[11] current thread:[140108241524480]
>>> 

You can access the inferior's locals and inspect them like so:

==> pid:[12679] #threads:[11] current thread:[140108241524480]
>>> inflocals()
{'a': <proxy of A object at remote 0x1d9b290>, 'LOL': 'success!', 'b': <proxy of B object at remote 0x1d988c0>, 'n': 1}
==> pid:[12679] #threads:[11] current thread:[140108241524480]
>>> p('a')
<proxy of A object at remote 0x1d9b290>
==> pid:[12679] #threads:[11] current thread:[140108241524480]
>>> p('a').attr
'Some_magic_string'
==> pid:[12679] #threads:[11] current thread:[140108241524480]
>>> 

And sure enough, the definition of a's class reads:

class Example(object):
  cl_attr = False
  def __init__(self):
    self.attr = 'Some_magic_string'

There's limits to how far this proxying of objects goes, and everything that isn't trivial data will show up as strings (like '<function at remote 0x1d957d0>').

View on GitHub


8.  python-hunter

Hunter is a flexible code tracing toolkit, not for measuring coverage, but for debugging, logging, inspection and other nefarious purposes. It has a simple Python API, a convenient terminal API and a CLI tool to attach to processes.

Installation

pip install hunter

Documentation

https://python-hunter.readthedocs.io/

Getting started

Basic use involves passing various filters to the trace option. An example:

import hunter
hunter.trace(module='posixpath', action=hunter.CallPrinter)

import os
os.path.join('a', 'b')

That would result in:

>>> os.path.join('a', 'b')
         /usr/lib/python3.6/posixpath.py:75    call      => join(a='a')
         /usr/lib/python3.6/posixpath.py:80    line         a = os.fspath(a)
         /usr/lib/python3.6/posixpath.py:81    line         sep = _get_sep(a)
         /usr/lib/python3.6/posixpath.py:41    call         => _get_sep(path='a')
         /usr/lib/python3.6/posixpath.py:42    line            if isinstance(path, bytes):
         /usr/lib/python3.6/posixpath.py:45    line            return '/'
         /usr/lib/python3.6/posixpath.py:45    return       <= _get_sep: '/'
         /usr/lib/python3.6/posixpath.py:82    line         path = a
         /usr/lib/python3.6/posixpath.py:83    line         try:
         /usr/lib/python3.6/posixpath.py:84    line         if not p:
         /usr/lib/python3.6/posixpath.py:86    line         for b in map(os.fspath, p):
         /usr/lib/python3.6/posixpath.py:87    line         if b.startswith(sep):
         /usr/lib/python3.6/posixpath.py:89    line         elif not path or path.endswith(sep):
         /usr/lib/python3.6/posixpath.py:92    line         path += sep + b
         /usr/lib/python3.6/posixpath.py:86    line         for b in map(os.fspath, p):
         /usr/lib/python3.6/posixpath.py:96    line         return path
         /usr/lib/python3.6/posixpath.py:96    return    <= join: 'a/b'
'a/b'

In a terminal it would look like:

https://raw.githubusercontent.com/ionelmc/python-hunter/master/docs/code-trace.png

Another useful scenario is to ignore all standard modules and force colors to make them stay even if the output is redirected to a file.

import hunter
hunter.trace(stdlib=False, action=hunter.CallPrinter(force_colors=True))

View on GitHub


9.  line_profiler

line_profiler is a module for doing line-by-line profiling of functions. kernprof is a convenient script for running either line_profiler or the Python standard library's cProfile or profile modules, depending on what is available.

Installation

Note: As of version 2.1.2, pip install line_profiler does not work. Please install as follows until it is fixed in the next release:

git clone https://github.com/rkern/line_profiler.git
find line_profiler -name '*.pyx' -exec cython {} \;
cd line_profiler
pip install . --user

Releases of line_profiler can be installed using pip:

$ pip install line_profiler

Source releases and any binaries can be downloaded from the PyPI link.

http://pypi.python.org/pypi/line_profiler

To check out the development sources, you can use Git:

$ git clone https://github.com/rkern/line_profiler.git

You may also download source tarballs of any snapshot from that URL.

Source releases will require a C compiler in order to build line_profiler. In addition, git checkouts will also require Cython >= 0.10. Source releases on PyPI should contain the pregenerated C sources, so Cython should not be required in that case.

kernprof is a single-file pure Python script and does not require a compiler. If you wish to use it to run cProfile and not line-by-line profiling, you may copy it to a directory on your PATH manually and avoid trying to build any C extensions.

View on GitHub


10.  Memory Profiler

This is a python module for monitoring memory consumption of a process as well as line-by-line analysis of memory consumption for python programs. It is a pure python module which depends on the psutil module.

Installation

To install through easy_install or pip:

$ easy_install -U memory_profiler # pip install -U memory_profiler

To install from source, download the package, extract and type:

$ python setup.py install

Usage

line-by-line memory usage

The line-by-line memory usage mode is used much in the same way of the line_profiler: first decorate the function you would like to profile with @profile and then run the script with a special script (in this case with specific arguments to the Python interpreter).

In the following example, we create a simple function my_func that allocates lists a, b and then deletes b:

@profile
def my_func():
    a = [1] * (10 ** 6)
    b = [2] * (2 * 10 ** 7)
    del b
    return a

if __name__ == '__main__':
    my_func()

Execute the code passing the option -m memory_profiler to the python interpreter to load the memory_profiler module and print to stdout the line-by-line analysis. If the file name was example.py, this would result in:

$ python -m memory_profiler example.py

Output will follow:

Line #    Mem usage  Increment   Line Contents
==============================================
     3                           @profile
     4      5.97 MB    0.00 MB   def my_func():
     5     13.61 MB    7.64 MB       a = [1] * (10 ** 6)
     6    166.20 MB  152.59 MB       b = [2] * (2 * 10 ** 7)
     7     13.61 MB -152.59 MB       del b
     8     13.61 MB    0.00 MB       return a

The first column represents the line number of the code that has been profiled, the second column (Mem usage) the memory usage of the Python interpreter after that line has been executed. The third column (Increment) represents the difference in memory of the current line with respect to the last one. The last column (Line Contents) prints the code that has been profiled.

View on GitHub


11.  py-spy

py-spy is a sampling profiler for Python programs. It lets you visualize what your Python program is spending time on without restarting the program or modifying the code in any way. py-spy is extremely low overhead: it is written in Rust for speed and doesn't run in the same process as the profiled Python program. This means py-spy is safe to use against production Python code.

py-spy works on Linux, OSX, Windows and FreeBSD, and supports profiling all recent versions of the CPython interpreter (versions 2.3-2.7 and 3.3-3.10).

Installation

Prebuilt binary wheels can be installed from PyPI with:

pip install py-spy

You can also download prebuilt binaries from the GitHub Releases Page.

If you're a Rust user, py-spy can also be installed with: cargo install py-spy.

On macOS, py-spy is in Homebrew and can be installed with brew install py-spy.

On Arch Linux, py-spy is in AUR and can be installed with yay -S py-spy.

On Alpine Linux, py-spy is in testing repository and can be installed with apk add py-spy --update-cache --repository http://dl-3.alpinelinux.org/alpine/edge/testing/ --allow-untrusted.

Usage

py-spy works from the command line and takes either the PID of the program you want to sample from or the command line of the python program you want to run. py-spy has three subcommands record, top and dump:

record

py-spy supports recording profiles to a file using the record command. For example, you can generate a flame graph of your python process by going:

py-spy record -o profile.svg --pid 12345
# OR
py-spy record -o profile.svg -- python myprogram.py

View on GitHub


12.  Pyflame

Pyflame is a high performance profiling tool that generates flame graphs for Python. Pyflame is implemented in C++, and uses the Linux ptrace(2) system call to collect profiling information. It can take snapshots of the Python call stack without explicit instrumentation, meaning you can profile a program without modifying its source code. Pyflame is capable of profiling embedded Python interpreters like uWSGI. It fully supports profiling multi-threaded Python programs.

Pyflame usually introduces significantly less overhead than the builtin profile (or cProfile) modules, and emits richer profiling data. The profiling overhead is low enough that you can use it to profile live processes in production.

Quickstart

Building And Installing

For Debian/Ubuntu, install the following:

# Install build dependencies on Debian or Ubuntu.
sudo apt-get install autoconf automake autotools-dev g++ pkg-config python-dev python3-dev libtool make

Once you have the build dependencies installed:

./autogen.sh
./configure
make

The make command will produce an executable at src/pyflame that you can run and use.

Optionally, if you have virtualenv installed, you can test the executable you produced using make check.

Using Pyflame

The full documentation for using Pyflame is here. But here's a quick guide:

# Attach to PID 12345 and profile it for 1 second
pyflame -p 12345

# Attach to PID 768 and profile it for 5 seconds, sampling every 0.01 seconds
pyflame -s 5 -r 0.01 -p 768

# Run py.test against tests/, emitting sample data to prof.txt
pyflame -o prof.txt -t py.test tests/

In all of these cases you will get flame graph data on stdout (or to a file if you used -o). This data is in the format expected by flamegraph.pl, which you can find here.

View on GitHub


13.  vprof

vprof is a Python package providing rich and interactive visualizations for various Python program characteristics such as running time and memory usage. It supports Python 3.4+ and distributed under BSD license.

The project is in active development and some of its features might not work as expected.

Installation

vprof can be installed from PyPI

pip install vprof

To build vprof from sources, clone this repository and execute

python3 setup.py deps_install && python3 setup.py build_ui && python3 setup.py install

To install just vprof dependencies, run

python3 setup.py deps_install

Usage

vprof -c <config> <src>

<config> is a combination of supported modes:

  • c - CPU flame graph ⚠️ Not available for windows #62

Shows CPU flame graph for <src>.

  • p - profiler

Runs built-in Python profiler on <src> and displays results.

  • m - memory graph

Shows objects that are tracked by CPython GC and left in memory after code execution. Also shows process memory usage after execution of each line of <src>.

  • h - code heatmap

Displays all executed code of <src> with line run times and execution counts.

View on GitHub


14.  Django Debug Toolbar

The Django Debug Toolbar is a configurable set of panels that display various debug information about the current request/response and when clicked, display more details about the panel's content.


Here's a screenshot of the toolbar in action:

Django Debug Toolbar screenshot

In addition to the built-in panels, a number of third-party panels are contributed by the community.

The current stable version of the Debug Toolbar is 3.6.0. It works on Django ≥ 3.2.4.

View on GitHub


15.  django-devserver

A drop in replacement for Django's built-in runserver command. Features include:

  • An extendable interface for handling things such as real-time logging.
  • Integration with the werkzeug interactive debugger.
  • Threaded (default) and multi-process development servers.
  • Ability to specify a WSGI application as your target environment.

Note

django-devserver works on Django 1.3 and newer

Installation

To install the latest stable version:

pip install git+git://github.com/dcramer/django-devserver#egg=django-devserver

django-devserver has some optional dependancies, which we highly recommend installing.

  • pip install sqlparse -- pretty SQL formatting
  • pip install werkzeug -- interactive debugger
  • pip install guppy -- tracks memory usage (required for MemoryUseModule)
  • pip install line_profiler -- does line-by-line profiling (required for LineProfilerModule)

You will need to include devserver in your INSTALLED_APPS:

INSTALLED_APPS = (
    ...
    'devserver',
)

If you're using django.contrib.staticfiles or any other apps with management command runserver, make sure to put devserver above any of them (or below, for Django<1.7). Otherwise devserver will log an error, but it will fail to work properly.

View on GitHub


16.  Flask Debug-toolbar

This is a port of the excellent django-debug-toolbar for Flask applications.

Installation

Installing is simple with pip:

$ pip install flask-debugtoolbar

Usage

Setting up the debug toolbar is simple:

from flask import Flask
from flask_debugtoolbar import DebugToolbarExtension

app = Flask(__name__)

# the toolbar is only enabled in debug mode:
app.debug = True

# set a 'SECRET_KEY' to enable the Flask session cookies
app.config['SECRET_KEY'] = '<replace with a secret key>'

toolbar = DebugToolbarExtension(app)

The toolbar will automatically be injected into Jinja templates when debug mode is on. In production, setting app.debug = False will disable the toolbar.

View on GitHub


17.  IceCream

Do you ever use print() or log() to debug your code? Of course you do. IceCream, or ic for short, makes print debugging a little sweeter.

ic() is like print(), but better:

  1. It prints both expressions/variable names and their values.
  2. It's 40% faster to type.
  3. Data structures are pretty printed.
  4. Output is syntax highlighted.
  5. It optionally includes program context: filename, line number, and parent function.

IceCream is well tested, permissively licensed, and supports Python 2, Python 3, PyPy2, and PyPy3. (Python 3.11 support is forthcoming.)

Inspect Variables

Have you ever printed variables or expressions to debug your program? If you've ever typed something like

print(foo('123'))

or the more thorough

print("foo('123')", foo('123'))

then ic() will put a smile on your face. With arguments, ic() inspects itself and prints both its own arguments and the values of those arguments.

from icecream import ic

def foo(i):
    return i + 333

ic(foo(123))

Prints

ic| foo(123): 456

Similarly,

d = {'key': {1: 'one'}}
ic(d['key'][1])

class klass():
    attr = 'yep'
ic(klass.attr)

Prints

ic| d['key'][1]: 'one'
ic| klass.attr: 'yep'

Just give ic() a variable or expression and you're done. Easy.

View on GitHub


18.  pyelftools

pyelftools is a pure-Python library for parsing and analyzing ELF files and DWARF debugging information. See the User's guide for more details.

Pre-requisites

As a user of pyelftools, one only needs Python 3 to run. For hacking on pyelftools the requirements are a bit more strict, please see the hacking guide.

Installing

pyelftools can be installed from PyPI (Python package index):

> pip install pyelftools

Alternatively, you can download the source distribution for the most recent and historic versions from the Downloads tab on the pyelftools project page (by going to Tags). Then, you can install from source, as usual:

> python setup.py install

Since pyelftools is a work in progress, it's recommended to have the most recent version of the code. This can be done by downloading the master zip file or just cloning the Git repository.

Since pyelftools has no external dependencies, it's also easy to use it without installing, by locally adjusting PYTHONPATH.

View on GitHub


FAQ about Debugging Tools python

  • How many types of debugging are in Python?

Debugging in any programming language typically involves two types of errors: syntax or logical. Syntax errors are those where the programming language commands are not interpreted by the compiler or interpreter because of a problem with how the program is written.

  • Best Debugging Tools include:

Chrome DevTools, Progress Telerik Fiddler, GDB (GNU Debugger), Data Display Debugger, SonarLint, Froglogic Squish, and TotalView HPC Debugging Software.

  • Why is it called debugging?

The terms "bug" and "debugging" are popularly attributed to Admiral Grace Hopper in the 1940s. While she was working on a Mark II computer at Harvard University, her associates discovered a moth stuck in a relay and thereby impeding operation, whereupon she remarked that they were "debugging" the system.

  • Why do we need debugging?

Debugging is important because it allows software engineers and developers to fix errors in a program before releasing it to the public. It's a complementary process to testing, which involves learning how an error affects a program overall.


Related videos:

Python Tutorial - Introduction to DEBUGGING


Related posts:

#python 

坂本  篤司

坂本 篤司

1652450700

Pythonグローバル変数–グローバル変数の例を定義する方法

この記事では、グローバル変数の基本を学びます。

まず、Pythonで変数を宣言する方法と、「変数スコープ」という用語が実際に何を意味するかを学習します。

次に、ローカル変数とグローバル変数の違いを学び、グローバル変数の定義方法とglobalキーワードの使用方法を理解します。

Pythonの変数とは何ですか?どのように作成しますか?初心者のための紹介

変数はストレージコンテナと考えることができます。

これらは、コンピュータのメモリに保存したいデータ、情報、および値を保持するためのストレージコンテナです。その後、プログラムの存続期間中のある時点でそれらを参照したり、操作したりすることもできます。

変数にはシンボリックがあり、その名前は、その識別子として機能するストレージコンテナのラベルと考えることができます。

変数名は、その中に格納されているデータへの参照とポインターになります。したがって、データと情報の詳細を覚えておく必要はありません。そのデータと情報を保持する変数名を参照するだけで済みます。

変数に名前を付けるときは、変数が保持するデータを説明していることを確認してください。変数名は、将来の自分自身と一緒に作業する可能性のある他の開発者の両方にとって、明確で簡単に理解できる必要があります。

それでは、Pythonで実際に変数を作成する方法を見てみましょう。

Pythonで変数を宣言するときは、データ型を指定する必要はありません。

たとえば、Cプログラミング言語では、変数が保持するデータの型を明示的に指定する必要があります。

したがって、整数またはint型である年齢を格納したい場合、これはCで行う必要があることです。

#include <stdio.h>
 
int main(void)
{
  int age = 28;
  // 'int' is the data type
  // 'age' is the name 
  // 'age' is capable of holding integer values
  // positive/negative whole numbers or 0
  // '=' is the assignment operator
  // '28' is the value
}

ただし、これはPythonで上記を記述する方法です。

age = 28

#'age' is the variable name, or identifier
# '=' is the assignment operator
#'28' is the value assigned to the variable, so '28' is the value of 'age'

変数名は常に左側にあり、代入する値は代入演算子の後に右側に配置されます。

プログラムの存続期間中、変数の値を変更できることに注意してください。

my_age = 28

print(f"My age in 2022 is {my_age}.")

my_age = 29

print(f"My age in 2023 will be {my_age}.")

#output

#My age in 2022 is 28.
#My age in 2023 will be 29.

同じ変数名を保持しますが、値をからにmy_age変更するだけです。2829

Pythonの可変スコープとはどういう意味ですか?

変数スコープとは、変数が利用可能で、アクセス可能で、表示可能なPythonプログラムの部分と境界を指します。

Python変数のスコープには4つのタイプがあり、 LEGBルールとも呼ばれます。

  • 局所
  • 囲み
  • グローバル
  • ビルトイン

この記事の残りの部分では、グローバルスコープを使用した変数の作成について学習することに焦点を当て、ローカル変数スコープとグローバル変数スコープの違いを理解します。

Pythonでローカルスコープを使用して変数を作成する方法

関数の本体内で定義された変数にはローカルスコープがあります。つまり、その特定の関数内でのみアクセスできます。言い換えれば、それらはその関数に対して「ローカル」です。

ローカル変数にアクセスするには、関数を呼び出す必要があります。

def learn_to_code():
    #create local variable
    coding_website = "freeCodeCamp"
    print(f"The best place to learn to code is with {coding_website}!")

#call function
learn_to_code()


#output

#The best place to learn to code is with freeCodeCamp!

関数の本体の外部からローカルスコープを使用してその変数にアクセスしようとするとどうなるかを見てください。

def learn_to_code():
    #create local variable
    coding_website = "freeCodeCamp"
    print(f"The best place to learn to code is with {coding_website}!")

#try to print local variable 'coding_website' from outside the function
print(coding_website)

#output

#NameError: name 'coding_website' is not defined

NameErrorプログラムの残りの部分では「表示」されないため、aが発生します。定義された関数内でのみ「表示」されます。

Pythonでグローバルスコープを使用して変数を作成する方法

ファイルの先頭など、関数の外部で変数を定義すると、その変数はグローバルスコープを持ち、グローバル変数と呼ばれます。

グローバル変数は、プログラムのどこからでもアクセスできます。

関数の本体内で使用することも、関数の外部からアクセスすることもできます。

#create a global variable
coding_website = "freeCodeCamp"

def learn_to_code():
    #access the variable 'coding_website' inside the function
    print(f"The best place to learn to code is with {coding_website}!")

#call the function
learn_to_code()

#access the variable 'coding_website' from outside the function
print(coding_website)

#output

#The best place to learn to code is with freeCodeCamp!
#freeCodeCamp

グローバル変数とローカル変数があり、両方が同じ名前の場合はどうなりますか?

#global variable
city = "Athens"

def travel_plans():
    #local variable with the same name as the global variable
    city = "London"
    print(f"I want to visit {city} next year!")

#call function - this will output the value of local variable
travel_plans()

#reference global variable - this will output the value of global variable
print(f"I want to visit {city} next year!")

#output

#I want to visit London next year!
#I want to visit Athens next year!

上記の例では、その特定の出力を期待していなかった可能性があります。

city関数内で別の値を割り当てたときに、の値が変わると思ったかもしれません。

たぶん、私が行でグローバル変数を参照したときprint(f" I want to visit {city} next year!")、出力は#I want to visit London next year!の代わりになると予想しました#I want to visit Athens next year!

ただし、関数が呼び出されると、ローカル変数の値が出力されます。

次に、関数の外部でグローバル変数を参照すると、グローバル変数に割り当てられた値が出力されました。

彼らはお互いに干渉しませんでした。

ただし、グローバル変数とローカル変数に同じ変数名を使用することは、ベストプラクティスとは見なされません。プログラムを実行すると混乱する結果が生じる可能性があるため、変数の名前が同じでないことを確認してください。

Pythonでキーワードを使用する方法global

グローバル変数があり、関数内でその値を変更したい場合はどうなりますか?

私がそれをしようとすると何が起こるか見てください:

#global variable
city = "Athens"

def travel_plans():
    #First, this is like when I tried to access the global variable defined outside the function. 
    # This works fine on its own, as you saw earlier on.
    print(f"I want to visit {city} next year!")

    #However, when I then try to re-assign a different value to the global variable 'city' from inside the function,
    #after trying to print it,
    #it will throw an error
    city = "London"
    print(f"I want to visit {city} next year!")

#call function
travel_plans()

#output

#UnboundLocalError: local variable 'city' referenced before assignment

デフォルトでは、Pythonは関数内でローカル変数を使用したいと考えています。

そのため、最初に変数の値を出力してから、アクセスしようとしている変数に値再割り当てしようとすると、Pythonが混乱します。

関数内のグローバル変数の値を変更する方法は、次のglobalキーワードを使用することです。

#global variable
city = "Athens"

#print value of global variable
print(f"I want to visit {city} next year!")

def travel_plans():
    global city
    #print initial value of global variable
    print(f"I want to visit {city} next year!")
    #assign a different value to global variable from within function
    city = "London"
    #print new value
    print(f"I want to visit {city} next year!")

#call function
travel_plans()

#print value of global variable
print(f"I want to visit {city} next year!")

global次のエラーが発生するため、関数でキーワードを参照する前にキーワードを使用してくださいSyntaxError: name 'city' is used prior to global declaration

以前、関数内で作成された変数はローカルスコープを持っているため、それらにアクセスできないことを確認しました。

globalキーワードは、関数内で宣言された変数の可視性を変更します。

def learn_to_code():
   global coding_website
   coding_website = "freeCodeCamp"
   print(f"The best place to learn to code is with {coding_website}!")

#call function
learn_to_code()

#access variable from within the function
print(coding_website)

#output

#The best place to learn to code is with freeCodeCamp!
#freeCodeCamp

結論

そして、あなたはそれを持っています!これで、Pythonのグローバル変数の基本を理解し、ローカル変数とグローバル変数の違いを理解できます。

この記事がお役に立てば幸いです。

基本から始めて、インタラクティブで初心者に優しい方法で学びます。また、最後に5つのプロジェクトを構築して実践し、学んだことを強化するのに役立てます。

読んでくれてありがとう、そして幸せなコーディング!

ソース:https ://www.freecodecamp.org/news/python-global-variables-examples/

#python 

Variables Globales De Python: Cómo Definir Un Ejemplo De Variable Glob

En este artículo, aprenderá los conceptos básicos de las variables globales.

Para empezar, aprenderá cómo declarar variables en Python y qué significa realmente el término 'ámbito de variable'.

Luego, aprenderá las diferencias entre variables locales y globales y comprenderá cómo definir variables globales y cómo usar la globalpalabra clave.

¿Qué son las variables en Python y cómo se crean? Una introducción para principiantes

Puede pensar en las variables como contenedores de almacenamiento .

Son contenedores de almacenamiento para almacenar datos, información y valores que le gustaría guardar en la memoria de la computadora. Luego puede hacer referencia a ellos o incluso manipularlos en algún momento a lo largo de la vida del programa.

Una variable tiene un nombre simbólico y puede pensar en ese nombre como la etiqueta en el contenedor de almacenamiento que actúa como su identificador.

El nombre de la variable será una referencia y un puntero a los datos almacenados en su interior. Por lo tanto, no es necesario recordar los detalles de sus datos e información; solo necesita hacer referencia al nombre de la variable que contiene esos datos e información.

Al dar un nombre a una variable, asegúrese de que sea descriptivo de los datos que contiene. Los nombres de las variables deben ser claros y fácilmente comprensibles tanto para usted en el futuro como para los otros desarrolladores con los que puede estar trabajando.

Ahora, veamos cómo crear una variable en Python.

Al declarar variables en Python, no necesita especificar su tipo de datos.

Por ejemplo, en el lenguaje de programación C, debe mencionar explícitamente el tipo de datos que contendrá la variable.

Entonces, si quisiera almacenar su edad, que es un número entero, o inttipo, esto es lo que tendría que hacer en C:

#include <stdio.h>
 
int main(void)
{
  int age = 28;
  // 'int' is the data type
  // 'age' is the name 
  // 'age' is capable of holding integer values
  // positive/negative whole numbers or 0
  // '=' is the assignment operator
  // '28' is the value
}

Sin embargo, así es como escribirías lo anterior en Python:

age = 28

#'age' is the variable name, or identifier
# '=' is the assignment operator
#'28' is the value assigned to the variable, so '28' is the value of 'age'

El nombre de la variable siempre está en el lado izquierdo y el valor que desea asignar va en el lado derecho después del operador de asignación.

Tenga en cuenta que puede cambiar los valores de las variables a lo largo de la vida de un programa:

my_age = 28

print(f"My age in 2022 is {my_age}.")

my_age = 29

print(f"My age in 2023 will be {my_age}.")

#output

#My age in 2022 is 28.
#My age in 2023 will be 29.

Mantienes el mismo nombre de variable my_age, pero solo cambias el valor de 28a 29.

¿Qué significa el alcance variable en Python?

El alcance de la variable se refiere a las partes y los límites de un programa de Python donde una variable está disponible, accesible y visible.

Hay cuatro tipos de alcance para las variables de Python, que también se conocen como la regla LEGB :

  • local ,
  • Encerrando ,
  • globales ,
  • Incorporado .

En el resto de este artículo, se centrará en aprender a crear variables con alcance global y comprenderá la diferencia entre los alcances de variables locales y globales.

Cómo crear variables con alcance local en Python

Las variables definidas dentro del cuerpo de una función tienen alcance local , lo que significa que solo se puede acceder a ellas dentro de esa función en particular. En otras palabras, son 'locales' para esa función.

Solo puede acceder a una variable local llamando a la función.

def learn_to_code():
    #create local variable
    coding_website = "freeCodeCamp"
    print(f"The best place to learn to code is with {coding_website}!")

#call function
learn_to_code()


#output

#The best place to learn to code is with freeCodeCamp!

Mire lo que sucede cuando trato de acceder a esa variable con un alcance local desde fuera del cuerpo de la función:

def learn_to_code():
    #create local variable
    coding_website = "freeCodeCamp"
    print(f"The best place to learn to code is with {coding_website}!")

#try to print local variable 'coding_website' from outside the function
print(coding_website)

#output

#NameError: name 'coding_website' is not defined

Plantea un NameErrorporque no es 'visible' en el resto del programa. Solo es 'visible' dentro de la función donde se definió.

Cómo crear variables con alcance global en Python

Cuando define una variable fuera de una función, como en la parte superior del archivo, tiene un alcance global y se conoce como variable global.

Se accede a una variable global desde cualquier parte del programa.

Puede usarlo dentro del cuerpo de una función, así como acceder desde fuera de una función:

#create a global variable
coding_website = "freeCodeCamp"

def learn_to_code():
    #access the variable 'coding_website' inside the function
    print(f"The best place to learn to code is with {coding_website}!")

#call the function
learn_to_code()

#access the variable 'coding_website' from outside the function
print(coding_website)

#output

#The best place to learn to code is with freeCodeCamp!
#freeCodeCamp

¿Qué sucede cuando hay una variable global y local, y ambas tienen el mismo nombre?

#global variable
city = "Athens"

def travel_plans():
    #local variable with the same name as the global variable
    city = "London"
    print(f"I want to visit {city} next year!")

#call function - this will output the value of local variable
travel_plans()

#reference global variable - this will output the value of global variable
print(f"I want to visit {city} next year!")

#output

#I want to visit London next year!
#I want to visit Athens next year!

En el ejemplo anterior, tal vez no esperaba ese resultado específico.

Tal vez pensaste que el valor de citycambiaría cuando le asignara un valor diferente dentro de la función.

Tal vez esperabas que cuando hice referencia a la variable global con la línea print(f" I want to visit {city} next year!"), la salida sería en #I want to visit London next year!lugar de #I want to visit Athens next year!.

Sin embargo, cuando se llamó a la función, imprimió el valor de la variable local.

Luego, cuando hice referencia a la variable global fuera de la función, se imprimió el valor asignado a la variable global.

No interfirieron entre sí.

Dicho esto, usar el mismo nombre de variable para variables globales y locales no se considera una buena práctica. Asegúrese de que sus variables no tengan el mismo nombre, ya que puede obtener algunos resultados confusos cuando ejecute su programa.

Cómo usar la globalpalabra clave en Python

¿Qué sucede si tiene una variable global pero desea cambiar su valor dentro de una función?

Mira lo que sucede cuando trato de hacer eso:

#global variable
city = "Athens"

def travel_plans():
    #First, this is like when I tried to access the global variable defined outside the function. 
    # This works fine on its own, as you saw earlier on.
    print(f"I want to visit {city} next year!")

    #However, when I then try to re-assign a different value to the global variable 'city' from inside the function,
    #after trying to print it,
    #it will throw an error
    city = "London"
    print(f"I want to visit {city} next year!")

#call function
travel_plans()

#output

#UnboundLocalError: local variable 'city' referenced before assignment

Por defecto, Python piensa que quieres usar una variable local dentro de una función.

Entonces, cuando intento imprimir el valor de la variable por primera vez y luego reasignar un valor a la variable a la que intento acceder, Python se confunde.

La forma de cambiar el valor de una variable global dentro de una función es usando la globalpalabra clave:

#global variable
city = "Athens"

#print value of global variable
print(f"I want to visit {city} next year!")

def travel_plans():
    global city
    #print initial value of global variable
    print(f"I want to visit {city} next year!")
    #assign a different value to global variable from within function
    city = "London"
    #print new value
    print(f"I want to visit {city} next year!")

#call function
travel_plans()

#print value of global variable
print(f"I want to visit {city} next year!")

Utilice la globalpalabra clave antes de hacer referencia a ella en la función, ya que obtendrá el siguiente error: SyntaxError: name 'city' is used prior to global declaration.

Anteriormente, vio que no podía acceder a las variables creadas dentro de las funciones ya que tienen un alcance local.

La globalpalabra clave cambia la visibilidad de las variables declaradas dentro de las funciones.

def learn_to_code():
   global coding_website
   coding_website = "freeCodeCamp"
   print(f"The best place to learn to code is with {coding_website}!")

#call function
learn_to_code()

#access variable from within the function
print(coding_website)

#output

#The best place to learn to code is with freeCodeCamp!
#freeCodeCamp

Conclusión

¡Y ahí lo tienes! Ahora conoce los conceptos básicos de las variables globales en Python y puede distinguir las diferencias entre las variables locales y globales.

Espero que hayas encontrado útil este artículo.

Comenzará desde lo básico y aprenderá de una manera interactiva y amigable para principiantes. También construirá cinco proyectos al final para poner en práctica y ayudar a reforzar lo que ha aprendido.

¡Gracias por leer y feliz codificación!

Fuente: https://www.freecodecamp.org/news/python-global-variables-examples/

#python