# Что такое библиотеки?
Библиотека или модуль — это набор готовых функций, объединенных общей темой. Например, в библиотеке math собраны функции для подсчёта математических величин.
Чтобы получить доступ к этим функциям, нужно командой import (англ. «импорт») в начале программы импортировать библиотеку. Это ещё называется «подключить модуль». В случае math пишут import math . Вот вызов извлекающей квадратный корень функции sqrt() из этой библиотеки:
Уже знакомая вам функция randint() из модуля random выбирает случайное целое число в заданном диапазоне. Но есть и другие, например:
- random.choice(список) вернёт случайный элемент из списка
- random.random() вернёт случайное дробное число от 0.0 до 1.0 (не включительно)
Если вам не нужны все функции библиотеки, можно подключить только нужные конструкцией from random import choice (из библиотеки random подключить функцию choice ).
Вот код для выбора подарка ребёнку. После явного подключения функции choice её можно использовать напрямую, без упоминания имени библиотеки.
Запустите этот код: результат может быть совсем другим!
Подключая библиотеку, можно присвоить ей новое имя. Например, если не хочется при каждом вызове писать полное имя:
math — Mathematical functions¶
This module provides access to the mathematical functions defined by the C standard.
These functions cannot be used with complex numbers; use the functions of the same name from the cmath module if you require support for complex numbers. The distinction between functions which support complex numbers and those which don’t is made since most users do not want to learn quite as much mathematics as required to understand complex numbers. Receiving an exception instead of a complex result allows earlier detection of the unexpected complex number used as a parameter, so that the programmer can determine how and why it was generated in the first place.
The following functions are provided by this module. Except when explicitly noted otherwise, all return values are floats.
Number-theoretic and representation functions¶
Return the ceiling of x, the smallest integer greater than or equal to x. If x is not a float, delegates to x.__ceil__ , which should return an Integral value.
Return the number of ways to choose k items from n items without repetition and without order.
Evaluates to n! / (k! * (n — k)!) when k <= n and evaluates to zero when k > n .
Also called the binomial coefficient because it is equivalent to the coefficient of k-th term in polynomial expansion of (1 + x)ⁿ .
Raises TypeError if either of the arguments are not integers. Raises ValueError if either of the arguments are negative.
New in version 3.8.
Return a float with the magnitude (absolute value) of x but the sign of y. On platforms that support signed zeros, copysign(1.0, -0.0) returns -1.0.
Return the absolute value of x.
math. factorial ( n ) ¶
Return n factorial as an integer. Raises ValueError if n is not integral or is negative.
Deprecated since version 3.9: Accepting floats with integral values (like 5.0 ) is deprecated.
Return the floor of x, the largest integer less than or equal to x. If x is not a float, delegates to x.__floor__ , which should return an Integral value.
Return fmod(x, y) , as defined by the platform C library. Note that the Python expression x % y may not return the same result. The intent of the C standard is that fmod(x, y) be exactly (mathematically; to infinite precision) equal to x — n*y for some integer n such that the result has the same sign as x and magnitude less than abs(y) . Python’s x % y returns a result with the sign of y instead, and may not be exactly computable for float arguments. For example, fmod(-1e-100, 1e100) is -1e-100 , but the result of Python’s -1e-100 % 1e100 is 1e100-1e-100 , which cannot be represented exactly as a float, and rounds to the surprising 1e100 . For this reason, function fmod() is generally preferred when working with floats, while Python’s x % y is preferred when working with integers.
Return the mantissa and exponent of x as the pair (m, e) . m is a float and e is an integer such that x == m * 2**e exactly. If x is zero, returns (0.0, 0) , otherwise 0.5 <= abs(m) < 1 . This is used to “pick apart” the internal representation of a float in a portable way.
math. fsum ( iterable ) ¶
Return an accurate floating point sum of values in the iterable. Avoids loss of precision by tracking multiple intermediate partial sums:
The algorithm’s accuracy depends on IEEE-754 arithmetic guarantees and the typical case where the rounding mode is half-even. On some non-Windows builds, the underlying C library uses extended precision addition and may occasionally double-round an intermediate sum causing it to be off in its least significant bit.
For further discussion and two alternative approaches, see the ASPN cookbook recipes for accurate floating point summation.
math. gcd ( * integers ) ¶
Return the greatest common divisor of the specified integer arguments. If any of the arguments is nonzero, then the returned value is the largest positive integer that is a divisor of all arguments. If all arguments are zero, then the returned value is 0 . gcd() without arguments returns 0 .
New in version 3.5.
Changed in version 3.9: Added support for an arbitrary number of arguments. Formerly, only two arguments were supported.
Return True if the values a and b are close to each other and False otherwise.
Whether or not two values are considered close is determined according to given absolute and relative tolerances.
rel_tol is the relative tolerance – it is the maximum allowed difference between a and b, relative to the larger absolute value of a or b. For example, to set a tolerance of 5%, pass rel_tol=0.05 . The default tolerance is 1e-09 , which assures that the two values are the same within about 9 decimal digits. rel_tol must be greater than zero.
abs_tol is the minimum absolute tolerance – useful for comparisons near zero. abs_tol must be at least zero.
If no errors occur, the result will be: abs(a-b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol) .
The IEEE 754 special values of NaN , inf , and -inf will be handled according to IEEE rules. Specifically, NaN is not considered close to any other value, including NaN . inf and -inf are only considered close to themselves.
New in version 3.5.
PEP 485 – A function for testing approximate equality
Return True if x is neither an infinity nor a NaN, and False otherwise. (Note that 0.0 is considered finite.)
New in version 3.2.
Return True if x is a positive or negative infinity, and False otherwise.
Return True if x is a NaN (not a number), and False otherwise.
Return the integer square root of the nonnegative integer n. This is the floor of the exact square root of n, or equivalently the greatest integer a such that a² ≤ n.
For some applications, it may be more convenient to have the least integer a such that n ≤ a², or in other words the ceiling of the exact square root of n. For positive n, this can be computed using a = 1 + isqrt(n — 1) .
New in version 3.8.
Return the least common multiple of the specified integer arguments. If all arguments are nonzero, then the returned value is the smallest positive integer that is a multiple of all arguments. If any of the arguments is zero, then the returned value is 0 . lcm() without arguments returns 1 .
New in version 3.9.
Return x * (2**i) . This is essentially the inverse of function frexp() .
Return the fractional and integer parts of x. Both results carry the sign of x and are floats.
Return the next floating-point value after x towards y.
math.nextafter(x, math.inf) goes up: towards positive infinity.
math.nextafter(x, -math.inf) goes down: towards minus infinity.
math.nextafter(x, 0.0) goes towards zero.
math.nextafter(x, math.copysign(math.inf, x)) goes away from zero.
New in version 3.9.
Return the number of ways to choose k items from n items without repetition and with order.
Evaluates to n! / (n — k)! when k <= n and evaluates to zero when k > n .
If k is not specified or is None, then k defaults to n and the function returns n! .
Raises TypeError if either of the arguments are not integers. Raises ValueError if either of the arguments are negative.
New in version 3.8.
Calculate the product of all the elements in the input iterable. The default start value for the product is 1 .
When the iterable is empty, return the start value. This function is intended specifically for use with numeric values and may reject non-numeric types.
New in version 3.8.
Return the IEEE 754-style remainder of x with respect to y. For finite x and finite nonzero y, this is the difference x — n*y , where n is the closest integer to the exact value of the quotient x / y . If x / y is exactly halfway between two consecutive integers, the nearest even integer is used for n . The remainder r = remainder(x, y) thus always satisfies abs(r) <= 0.5 * abs(y) .
Special cases follow IEEE 754: in particular, remainder(x, math.inf) is x for any finite x, and remainder(x, 0) and remainder(math.inf, x) raise ValueError for any non-NaN x. If the result of the remainder operation is zero, that zero will have the same sign as x.
On platforms using IEEE 754 binary floating-point, the result of this operation is always exactly representable: no rounding error is introduced.
New in version 3.7.
Return x with the fractional part removed, leaving the integer part. This rounds toward 0: trunc() is equivalent to floor() for positive x, and equivalent to ceil() for negative x. If x is not a float, delegates to x.__trunc__ , which should return an Integral value.
Return the value of the least significant bit of the float x:
If x is a NaN (not a number), return x.
If x is negative, return ulp(-x) .
If x is a positive infinity, return x.
If x is equal to zero, return the smallest positive denormalized representable float (smaller than the minimum positive normalized float, sys.float_info.min ).
If x is equal to the largest positive representable float, return the value of the least significant bit of x, such that the first float smaller than x is x — ulp(x) .
Otherwise (x is a positive finite number), return the value of the least significant bit of x, such that the first float bigger than x is x + ulp(x) .
ULP stands for “Unit in the Last Place”.
New in version 3.9.
Note that frexp() and modf() have a different call/return pattern than their C equivalents: they take a single argument and return a pair of values, rather than returning their second return value through an ‘output parameter’ (there is no such thing in Python).
For the ceil() , floor() , and modf() functions, note that all floating-point numbers of sufficiently large magnitude are exact integers. Python floats typically carry no more than 53 bits of precision (the same as the platform C double type), in which case any float x with abs(x) >= 2**52 necessarily has no fractional bits.
Power and logarithmic functions¶
Return the cube root of x.
New in version 3.11.
Return e raised to the power x, where e = 2.718281… is the base of natural logarithms. This is usually more accurate than math.e ** x or pow(math.e, x) .
Return 2 raised to the power x.
New in version 3.11.
Return e raised to the power x, minus 1. Here e is the base of natural logarithms. For small floats x, the subtraction in exp(x) — 1 can result in a significant loss of precision; the expm1() function provides a way to compute this quantity to full precision:
New in version 3.2.
With one argument, return the natural logarithm of x (to base e).
With two arguments, return the logarithm of x to the given base, calculated as log(x)/log(base) .
Return the natural logarithm of 1+x (base e). The result is calculated in a way which is accurate for x near zero.
Return the base-2 logarithm of x. This is usually more accurate than log(x, 2) .
New in version 3.3.
int.bit_length() returns the number of bits necessary to represent an integer in binary, excluding the sign and leading zeros.
Return the base-10 logarithm of x. This is usually more accurate than log(x, 10) .
Return x raised to the power y . Exceptional cases follow the IEEE 754 standard as far as possible. In particular, pow(1.0, x) and pow(x, 0.0) always return 1.0 , even when x is a zero or a NaN. If both x and y are finite, x is negative, and y is not an integer then pow(x, y) is undefined, and raises ValueError .
Unlike the built-in ** operator, math.pow() converts both its arguments to type float . Use ** or the built-in pow() function for computing exact integer powers.
Changed in version 3.11: The special cases pow(0.0, -inf) and pow(-0.0, -inf) were changed to return inf instead of raising ValueError , for consistency with IEEE 754.
Return the square root of x.
Trigonometric functions¶
Return the arc cosine of x, in radians. The result is between 0 and pi .
Return the arc sine of x, in radians. The result is between -pi/2 and pi/2 .
Return the arc tangent of x, in radians. The result is between -pi/2 and pi/2 .
Return atan(y / x) , in radians. The result is between -pi and pi . The vector in the plane from the origin to point (x, y) makes this angle with the positive X axis. The point of atan2() is that the signs of both inputs are known to it, so it can compute the correct quadrant for the angle. For example, atan(1) and atan2(1, 1) are both pi/4 , but atan2(-1, -1) is -3*pi/4 .
Return the cosine of x radians.
Return the Euclidean distance between two points p and q, each given as a sequence (or iterable) of coordinates. The two points must have the same dimension.
Roughly equivalent to:
New in version 3.8.
Return the Euclidean norm, sqrt(sum(x**2 for x in coordinates)) . This is the length of the vector from the origin to the point given by the coordinates.
For a two dimensional point (x, y) , this is equivalent to computing the hypotenuse of a right triangle using the Pythagorean theorem, sqrt(x*x + y*y) .
Changed in version 3.8: Added support for n-dimensional points. Formerly, only the two dimensional case was supported.
Changed in version 3.10: Improved the algorithm’s accuracy so that the maximum error is under 1 ulp (unit in the last place). More typically, the result is almost always correctly rounded to within 1/2 ulp.
Return the sine of x radians.
Return the tangent of x radians.
Angular conversion¶
Convert angle x from radians to degrees.
Convert angle x from degrees to radians.
Hyperbolic functions¶
Hyperbolic functions are analogs of trigonometric functions that are based on hyperbolas instead of circles.
Return the inverse hyperbolic cosine of x.
Return the inverse hyperbolic sine of x.
Return the inverse hyperbolic tangent of x.
Return the hyperbolic cosine of x.
Return the hyperbolic sine of x.
Return the hyperbolic tangent of x.
Special functions¶
The erf() function can be used to compute traditional statistical functions such as the cumulative standard normal distribution:
New in version 3.2.
Return the complementary error function at x. The complementary error function is defined as 1.0 — erf(x) . It is used for large values of x where a subtraction from one would cause a loss of significance.
New in version 3.2.
New in version 3.2.
Return the natural logarithm of the absolute value of the Gamma function at x.
New in version 3.2.
Constants¶
The mathematical constant π = 3.141592…, to available precision.
The mathematical constant e = 2.718281…, to available precision.
The mathematical constant τ = 6.283185…, to available precision. Tau is a circle constant equal to 2π, the ratio of a circle’s circumference to its radius. To learn more about Tau, check out Vi Hart’s video Pi is (still) Wrong, and start celebrating Tau day by eating twice as much pie!
New in version 3.6.
A floating-point positive infinity. (For negative infinity, use -math.inf .) Equivalent to the output of float(‘inf’) .
New in version 3.5.
A floating-point “not a number” (NaN) value. Equivalent to the output of float(‘nan’) . Due to the requirements of the IEEE-754 standard, math.nan and float(‘nan’) are not considered to equal to any other numeric value, including themselves. To check whether a number is a NaN, use the isnan() function to test for NaNs instead of is or == . Example:
Changed in version 3.11: It is now always available.
New in version 3.5.
CPython implementation detail: The math module consists mostly of thin wrappers around the platform C math library functions. Behavior in exceptional cases follows Annex F of the C99 standard where appropriate. The current implementation will raise ValueError for invalid operations like sqrt(-1.0) or log(0.0) (where C99 Annex F recommends signaling invalid operation or divide-by-zero), and OverflowError for results that overflow (for example, exp(1000.0) ). A NaN will not be returned from any of the functions above unless one or more of the input arguments was a NaN; in that case, most functions will return a NaN, but (again following C99 Annex F) there are some exceptions to this rule, for example pow(float(‘nan’), 0.0) or hypot(float(‘nan’), float(‘inf’)) .
Note that Python makes no effort to distinguish signaling NaNs from quiet NaNs, and behavior for signaling NaNs remains unspecified. Typical behavior is to treat all NaNs as though they were quiet.
Система импорта Python
![]()
Мы видели много преимуществ системы импорта Python и способов их использования. В этой статье мы приподнимем завесу над тем, что происходит при импорте модулей и пакетов.
Как и многое в Python, систему импорта можно настраивать. Мы увидим несколько способов изменения системы импорта, в том числе автоматическую загрузку недостающих пакетов из PyPI и импорт файлов данных, как если бы они были модулями.
Импорт содержимого модулей
Система импорта Python подробно описана в официальной документации. Вот что происходит на высоком уровне при импорте модуля (или пакета). Модуль:
- Ищется.
- Загружается.
- Привязывается к пространству имён.
Для обычных импортов, выполняемых с помощью оператора import , все три пункта происходят автоматически. А вот при использовании importlib автоматически срабатывают только первые два. Привязывать модуль к переменной или пространству имён придётся самостоятельно.
Например, следующие способы импортирования и переименования math.pi примерно эквивалентны:
Конечно, в обычном коде вы бы отдали предпочтение первому.
Следует отметить, что даже если из модуля импортируется только один атрибут, то загружается и выполняется весь модуль. Остальное содержимое модуля просто не привязано к текущему пространству имён. Чтобы доказать это, обратимся к кэшу модулей:
sys.modules — это и есть кэш модулей. Он содержит ссылки на все импортированные модули.
Кэш модулей играет очень важную роль в системе импорта Python. Именно здесь, в sys.modules , прежде чем где-либо ещё, Python ищет модули при выполнении импорта. Если модуль уже доступен, то он не загружается снова.
Это не только отличная оптимизация, но и необходимость. Если бы модули при каждом импортировании загружались заново, то в некоторых ситуациях могли бы возникнуть несоответствия (например, когда имеющийся исходный код меняется во время выполнения скрипта).
Вспомните путь импорта, который вы рассматривали ранее, в первой статье. Фактически он сообщает Python, где искать модули. Но если Python находит модуль в кэше модулей, то он не станет утруждать себя поиском пути импорта для этого модуля.
Пример: синглтоны в качестве модулей
В объектно-ориентированном программировании синглтон — это класс, имеющий не более одного экземпляра. И хотя мы можем реализовать синглтоны в Python, большинство случаев хорошего использования синглтонов связано с модулями. Мы можем доверить кэшу модулей инстанцирование класса только один раз.
В качестве примера вернемся к демографическим данным Организации Объединенных Наций, которые мы уже рассматривали ранее, в первой статье. Следующий модуль определяет класс, обёртывающий данные о населении:
Чтение данных с диска занимает некоторое время. Мы не ожидаем, что файл данных изменится, поэтому инстанцируем класс при загрузке модуля. Название класса начинается с подчеркивания для указания на то, что его не следует использовать.
Мы можем задействовать синглтон population.data для создания диаграммы Matplotlib, иллюстрирующей демографический прогноз для стран с наибольшей численностью населения:
Создаётся такой график:
Обратите внимание, что загрузка данных во время импорта — это своего рода антипаттерн. В идеале желательно, чтобы импорт был максимально свободен от побочных эффектов. Лучшим подходом была бы ленивая загрузка данных, т.е. загружать их по мере необходимости. Это может получаться довольно элегантно, если мы задействуем свойства. Пример того, как это делается, можете увидеть ниже.
Ленивая реализация population сохраняет демографические данные в ._data в момент, когда они впервые считываются. Свойство .data работает с этим кэшированием данных:
Повторная загрузка модулей
Кэш модулей может быть несколько неудобным, когда вы работаете в интерактивном интерпретаторе. Не так просто перезагрузить модуль после его изменения. Рассмотрим, например, следующий модуль:
Выполняя тестирование и отладку этого модуля, импортируем его в консоль Python:
Допустим, мы нашли ошибку в коде, поэтому обновляем файл number.py в редакторе:
Вернувшись в консоль, импортируем обновленный модуль, чтобы увидеть, что получилось после исправления ошибки:
Почему ответ всё тот же: 24 ? Кэш модулей делает свою (теперь доставляющую некоторые неудобства) работу: Python уже импортировал ранее number , поэтому он не видит причин загружать этот модуль снова, даже если в него только что внесли изменения.
Самое простое решение здесь — выйти из консоли Python и перезапустить её. Это заставит Python очистить свой кэш модулей:
Однако перезапуск интерпретатора не всегда возможен. Вероятно, виной тому более сложная сессия, на настройку которой может уйти много времени. В этом случае для перезагрузки модуля можно использовать importlib.reload() :
Обратите внимание, что объекта модуля требует reload() , а не строка типа import_module() . Кроме того, у reload() есть кое-какие нюансы. В частности: переменные, ссылающиеся на объекты внутри модуля, не привязываются повторно к новым объектам при перезагрузке этого модуля. С подробностями можно ознакомиться в документации.
Средства поиска и загрузчики
Мы уже видели, что создание модулей с теми же именами, что и стандартные библиотеки, может приводить к проблемам. Например, если у нас в пути импорта Python есть файл с именем math.py , мы не сможем импортировать math из стандартной библиотеки.
Но это не всегда так. Создадим файл с именем time.py и таким содержимым:
Затем откроем интерпретатор Python и импортируем этот новый модуль:
Но тут что-то странное случилось. Похоже, Python не импортировал наш новый модуль time . Вместо него был импортирован модуль time из стандартной библиотеки. Почему стандартные библиотечные модули ведут себя непоследовательно? Ответить на этот вопрос мы сможем, внимательно рассмотрев модули:
Модуль math импортируется из файла, а вот time — это уже встроенный модуль. Кажется, встроенные модули не затеняются локальными.
Примечание: встроенные модули компилируются в интерпретатор Python. Это в основном базовые модули, такие как builtins , sys и time . Какие именно модули встроенные, зависит от интерпретатора Python. Их имена можно найти в sys.builtin_module_names .
Давайте ещё больше углубимся в систему импорта Python, а заодно разберёмся, почему встроенные модули не затеняются локальными. Импортирование модуля проходит в три этапа:
- Python проверяет, доступен ли модуль в кэше модулей. Если sys.modules присутствует имя этого модуля, то это значит, что модуль уже доступен и процесс импорта завершается.
- Python начинает искать модуль с помощью средств поиска. Средство поиска ищет модуль, используя заданную стратегию. Стандартные средства поиска могут импортировать встроенные модули, замороженные модули и модули, находящиеся в пути импорта.
- Python загружает модуль с помощью загрузчика. Какой именно загрузчик используется в Python? Это определяется средством поиска, которое находит модуль. Загрузчик указывается в module spec.
Вы можете расширить систему импорта Python, внедрив своё собственное средство поиска и при необходимости — собственный загрузчик. Позже мы увидим пример использования такого средства поиска. А пока что научимся делать базовые (и совсем простенькие) персональные настройки системы импорта.
sys.meta_path управляет тем, какие средства поиска вызываются в процессе импорта:
Стоит обратить внимание на два обстоятельства. Во-первых, здесь даётся ответ на поставленный ранее вопрос: встроенные модули не затеняются локальными модулями, потому что встроенное средство поиска вызывается до средства поиска пути импорта, которое находит локальные модули. Во-вторых, есть возможность настроить sys.meta_path так, как вам нужно.
Внесём немного неразберихи в наш сеанс работы в Python. Для этого удалим все средства поиска:
Средств поиска не осталось, поэтому Python не может найти или импортировать новые модули. Но у Python остаётся возможность импортировать те модули, которые уже находятся в кэше модулей. Он заглядывает туда, прежде чем вызывать средства поиска.
В приведённом выше примере importlib был загружен уже до того, как мы убрали средства поиска. Теперь сделаем наш сеанс работы в Python полностью непригодным. Для этого очистим также и кэш модуля sys.modules .
Далее приведём более полезный пример. Напишем средство поиска, которое выведет на консоль сообщение, идентифицирующее импортируемый модуль. В этом примере показано, как добавить собственное средство поиска, пусть и фактически без попыток найти модуль:
Все средства поиска должны реализовывать метод класса .find_spec() , пытающийся найти данный модуль. Есть три способа завершения метода .find_spec() :
- С возвращениемNone , если он не знает, как найти и загрузить модуль.
- С возвращением module spec, указывающим на то, как загрузить модуль.
- С выдачей ошибкиModuleNotFoundError , указывающей на то, что модуль не может быть импортирован.
DebugFinder выводит на консоль сообщение, а затем явным образом возвращает None , фактически оставляя импорт модуля другим средствам поиска.
Обратите внимание: Python неявно возвращает None из любой функции или метода (не указывая return ), поэтому строчку 9 можно опустить. Но в данном случае мы включаем return None , давая понять, что DebugFinder не находит модуль.
Вставив DebugFinder первым в список средств поиска, получаем рабочий список всех импортируемых модулей:
Например, можем видеть, что импорт csv запускает импорт нескольких других модулей, от которых csv зависит. Обратите внимание, что параметр python -v интерпретатора Python даёт ту же информацию и много других данных.
Или вот ещё пример: скажем, у нас задача избавить мир от регулярных выражений. (Но к чему такая категоричность? Регулярные выражения — это здорово!). Мы можем реализовать средство поиска, которое запрещает модуль регулярных выражений re :
Появление ModuleNotFoundError гарантирует, что ни одно из средств поиска, идущих далее в списке средств поиска, выполнено не будет. Тем самым обеспечивается неиспользование регулярных выражений в Python:
Даже если мы импортируем только csv , этот модуль попутно импортирует и re , поэтому возникает ошибка.
Пример: автоматическая установка из PyPI
Система импорта Python уже достаточно мощная и удобная, поэтому куда проще внести в неё сумятицу, чем дополнить чем-то полезным. Однако следующий пример в определенных ситуациях может пригодиться.
Каталог пакетов Python Package Index (PyPI) — это универсальный каталог программного обеспечения для поиска сторонних модулей и пакетов. Кроме того, это место, откуда pip загружает пакеты.
Вы, возможно, уже видели инструкции с примерами по использованию python -m pip install для установки сторонних модулей и пакетов. Разве не здорово было бы, если бы Python автоматически устанавливал за вас недостающие модули?
Предупреждение: в большинстве случаев было бы совсем не здорово, если бы Python устанавливал модули автоматически. Например, в большинстве производственных настроек надо сохранять контроль над средой. Кроме того, в документации рекомендуется воздерживаться от такого использования pip .
Во избежание ошибок при установке модулей в Python следует экспериментировать с этим кодом только в тех средах, которые не жалко будет удалить или переустановить.
Следующее средство поиска пытается установить модули с помощью pip :
Это средство поиска немного сложнее тех, что мы видели ранее. Поставив его последним в списке средств поиска, вы будете знать, что при вызове PipFinder этого модуля не будет в вашем компьютере. Поэтому работа метода .find_spec() — просто выполнить pip install . Если установка выполнится, будет создан и возвращен module spec.
Попробуйте сами использовать библиотеку parse , не устанавливая её:
Обычно import parse не приводит к появлению ошибки ModuleNotFoundError , но в этом случае устанавливается и импортируется parse .
Хотя PipFinder вроде бы работает, с этим подходом связаны некоторые трудности. Основная проблема в том, что имя импорта модуля не всегда соответствует его имени в PyPI. Например, Real Python feed reader называется realpython-reader в PyPI, а имя импорта у него — reader .
Применение PipFinder для импорта и установки reader приводит к установке неправильного пакета:
Это может иметь катастрофические последствия для вашего проекта.
Автоматическая установка может быть очень полезна при запуске Python в облаке с более ограниченным контролем над средой. Например, когда вы запускаете инструменты типа Jupyter notebook в Google Colaboratory. Среда Colab notebook отлично подходит для совместного просмотра данных.
Типичная среда notebook идёт с кучей установленных пакетов для обработки и анализа данных, таких как NumPy, Pandas и Matplotlib, а с помощью pip можно добавлять новые пакеты. Кроме того, можно активировать автоматическую установку:
pip_importer недоступен локально на сервере Colab, поэтому код копируется в первую ячейку notebook.
Пример: импорт файлов данных
Последний пример в этой части составлен по мотивам замечательной статьи Алексея Билогура Import Almost Anything in Python: An Intro to Module Loaders and Finders (eng). Мы уже видели, как использовать importlib.resources для импорта файлов данных. Здесь же мы реализуем пользовательский загрузчик, который может импортировать CSV-файл напрямую.
Ранее у нас был огромный CSV-файл с демографическими данными. Сделаем пример пользовательского загрузчика более управляемым с помощью файла меньшего размера employees.csv :
Первая строка представляет собой заголовок с названиями для трёх полей, а следующие две строки содержат информацию о сотрудниках. Ещё больше о работе с CSV-файлами можно узнать в статье Reading and Writing CSV Files in Python (eng).
Наша цель в этой части статьи — написать средство поиска и загрузчик, позволяющие импортировать CSV-файл напрямую, так чтобы можно было написать такой код:
Средство поиска должно будет находить и распознавать CSV-файлы. А загрузчик — импортировать данные в формате CSV. Средства поиска и соответствующие им загрузчики зачастую можно реализовать в одном общем классе. Именно такой подход мы здесь и применим:
В этом примере довольно много кода! К счастью, большая часть работы сделана в .find_spec() и .exec_module() . Рассмотрим их подробнее.
Мы уже видели, что .find_spec() отвечает за поиск модуля. В этом случае мы ищем CSV-файлы, поэтому создаём имя файла с расширением .csv . name содержит полное имя импортируемого модуля. Например, если у нас from data import employees , то именем name будет data.employees . В этом случае имя файла будет employees.csv .
Для импорта верхнего уровня path (путь) будет None . В этом случае мы ищем CSV-файл в полном пути импорта, который будет включать текущий рабочий каталог. Если импортируется CSV-файл внутри пакета, path примет значение пути или путей этого пакета. При нахождении соответствующего CSV-файла обратно будет возвращён module spec. Этот module spec указывает Python на CsvImporter для загрузки модуля.
Данные в формате CSV загружаются через .exec_module() . Для парсинга файла можно использовать csv.DictReader из стандартной библиотеки. В Python для многих вещей, в том числе и модулей, есть возможность создавать словари. Добавляя данные в формате CSV в module.__dict__ , мы делаем их доступными в качестве атрибутов модуля.
Например, добавив fieldnames (имена полей) в словарь модуля в строке 44, можно увидеть имена полей в CSV-файле:
Вообще-то имена полей CSV могут содержать пробелы и другие символы, которые не могут использоваться в именах атрибутов Python. Прежде чем попасть в модуль в качестве атрибутов, имена полей очищаются при помощи регулярного выражения. Это делается в _identifier() , начиная со строки 51.
В качестве примера можно взять имя поля birthday_month . Если обратиться к исходному CSV-файлу, то увидим, что в заголовке birthday month вместо подчеркивания стоит пробел.
Подключив к системе импорта Python этот CsvImporter , вот так просто получаем довольно много функциональности. Кэш модулей, например, позаботится о том, чтобы файл данных загружался только один раз.
Импорт: полезные советы
В завершение статьи покажем несколько хитрых приёмов, помогающих справиться с определёнными ситуациями, которые время от времени возникают. Увидим, как быть с недостающими пакетами, циклическим импортом и даже пакетами, хранящимися в ZIP-файлах.
Пакеты в разных версиях Python
Иногда приходится иметь дело с пакетами, имена которых отличаются в разных версиях Python. Мы уже видели, как importlib.resources были доступны только начиная с Python 3.7. В более ранних версиях Python приходится устанавливать importlib_resources .
Пока различные версии пакета совместимы, мы можем просто переименовывать пакет с помощью as :
В остальной части кода можно ссылаться на resources и не задумываться о том, что там у нас — importlib.resources или importlib_resources .
Чтобы определиться с версией, обычно проще всего использовать конструкцию try. except . Другой вариант — свериться с версией интерпретатора Python. Однако это может быть чревато увеличением затрат на сопровождение кода, в случае если возникнет необходимость обновить номера версий.
Предыдущий пример можно переписать следующим образом:
То есть на Python 3.7 и более новых версиях будем применять importlib.resources , а на более старых версиях Python будем возвращаться к importlib_resources . Смотрите проект flake8-2020 с хорошими и перспективными рекомендациями о том, как проверить, какая версия Python работает.
Недостающие пакеты: используем альтернативу
Следующий сценарий применения тесно связан с предыдущим примером. Предположим, у нас есть совместимая повторная реализация пакета. Повторная реализация лучше оптимизирована, поэтому желательно использовать её, если она доступна. Но исходный пакет ещё более доступен и к тому же обеспечивает приемлемую производительность.
Один из примеров — quicktions , оптимизированная версия fractions из стандартной библиотеки. Мы можем работать с этими параметрами так же, как делали это с разными именами пакетов чуть ранее:
Будет использован quicktions , если он доступен. В противном случае — fractions .
Похожий пример — пакет UltraJSON, сверхбыстрый кодер и декодер JSON, который может заменить json из стандартной библиотеки:
Переименовываем ujson в json и не задумываемся о том, какой именно пакет импортирован.
Недостающие пакеты: используем имитированную реализацию
Третий пример, похожий на два предыдущих, — добавление пакета с необязательным для приложения, но приятным функционалом. Здесь опять же добавляем к импорту try. except . Дополнительную сложность представляет замена опционального пакета, если он недоступен.
Конкретизируем пример: будем использовать Colorama для добавления цветного текста в консоль. Colorama в основном состоит из специальных строковых констант, которые добавляют цвет при выводе на печать:
К сожалению, цвет не отображается в приведенном выше примере. В терминале он будет выглядеть примерно так:
Прежде чем начинать использовать цвета Colorama, вызываем colorama.init() . Установка autoreset на True приводит к тому, что цветовые директивы будут автоматически сброшены в конце строки. Такая настройка пригодится, в случае если вам нужно выделить в цвете только одну строку.
Если же вы захотите вывести всё, например в синем цвете, то установите autoreset на False и добавьте Fore.BLUE к началу скрипта. Доступны следующие цвета:
Также есть возможность выбрать стиль текста с помощью colorama.Style . Доступны DIM (тусклый), NORMAL (нормальный) и BRIGHT (яркий).
И наконец, есть colorama.Cursor с кодом для управления положением курсора. Можно использовать для отображения хода выполнения или статуса запущенного скрипта. В следующем примере показывается обратный отсчет от 10 :
Обратите внимание: счётчик остается на месте, обратный отсчёт не показывается на отдельных строках, как происходит обычно:
Вернёмся к нашей задаче. Для многих приложений добавление цвета в консольный вывод — это круто, но не так чтобы очень необходимо. Чтобы не добавлять приложению очередную зависимость, надо использовать Colorama только в том случае, если последняя есть на компьютере, и не ломать приложение, если её нет.
Для этого можно попробовать тестирование и использование моков. Мок может заменить другой объект, позволяя контролировать его поведение. Вот наивная попытка сымитировать Colorama:
Но она не совсем работает, потому что Fore.RED представлен строкой, которая вносит сумятицу в вывод. В то время как нужно создать объект, который всегда выводит на экран пустую строку.
Можно изменить возвращаемое значение .__str__() в Mock -объектах. Но в этом случае удобнее написать свой мок:
ColoramaMock("") — это пустая строка, которая при вызове также возвращает пустую строку. Это фактически даёт нам повторную реализацию Colorama, только без цветов.
И последняя особенность: .__getattr__() возвращает сам себя, так что все цвета, стили, а также перемещения курсора, являющиеся атрибутами в Back , Fore , Style и Cursor , тоже имитируются.
Модуль optional_color служит упрощённой заменой Colorama, поэтому мы можем обновить пример с обратным отсчётом с помощью поиска и замены:
Если запустить этот скрипт на компьютере без Colorama, он всё равно будет работать, разве что выглядеть может не так изящно:
А с установленной Colorama результаты будут такими же, что мы видели раньше.
Импорт скриптов в качестве модулей
Отличие скриптов от библиотечных модулей состоит в том, что скрипты обычно что-то делают, библиотеки же обеспечивают функциональность. И скрипты, и библиотеки находятся внутри обычных файлов Python, и с точки зрения Python между ними нет никакой разницы.
Разница в том, как файл должен использоваться: выполняться с помощью python file.py или импортироваться с помощью import file внутри другого скрипта?
Когда у вас есть модуль, который работает как скрипт и библиотека, можно попробовать выполнить рефакторинг этого модуля на два разных файла.
Один из примеров этого есть в стандартной библиотеке — пакет json . Обычно он используется как библиотека, но в нём есть скрипт, который может придать файлам JSON более привлекательный вид. Представьте, что у вас есть такой файл colors.json :
JSON часто читаются только машинами, поэтому многие файлы JSON не форматируются в виде, удобном для восприятия человеком. Так что файлы JSON, состоящие из одной очень длинной строки текста, — явление распространенное.
json.tool — это скрипт, который использует библиотеку json для форматирования JSON в более удобной для восприятия человеком форме:
Теперь структура JSON-файла становится гораздо менее сложной для понимания. Ключи можно отсортировать в алфавитном порядке. Для этого есть опция —sort-keys .
Разделение скриптов и библиотек — это хорошая практика. Тем не менее в Python есть идиома, благодаря которой можно обращаться с модулем как скриптом и библиотекой одновременно. Как мы уже видели ранее, значение специальной переменной модуля __name__ устанавливается во время выполнения в зависимости от того, импортируется ли модуль или выполняется как скрипт.
Давайте проверим это! Создадим следующий файл:
При запуске этого файла увидим, что __name__ имеет специальное значение __main__ :
Но при импорте этого модуля значением __name__ будет имя модуля:
Это поведение используется в следующем шаблоне:
Возьмём пример побольше. Оставаться вечно молодыми нам поможет следующий скрипт, в котором любой «старый» возраст ( 25 года или больше) будет заменяться на 24 года:
Можно запустить это как скрипт, и он в интерактивном режиме будет делать вводимый вами возраст меньше:
Можно использовать этот модуль и в качестве импортируемой библиотеки. Проверка условия if в строке 12 исключает какие-либо побочные эффекты при импорте библиотеки. Определены только функции make_young() и replace_by_age() . Вы можете, например, использовать эту библиотеку вот так:
Не будь защиты проверки условия if , импорт запустил бы интерактивный input() , после чего использовать feel_young в качестве библиотеки стало бы очень сложно.
Запуск скриптов Python из ZIP-файлов
Немного неясной представляется способность Python запускать скрипты, упакованные в ZIP-файлы. Её главное преимущество в возможности распространять весь пакет одним файлом.
Однако для этого нужно, чтобы Python был установлен на компьютере. Если хотите распространять свое приложение Python как автономный исполняемый файл, смотрите статью Using PyInstaller to Easily Distribute Python Applications (eng).
Если дать интерпретатору Python ZIP-файл, то он будет искать файл с именем __main__.py внутри ZIP-архива, извлечёт его и запустит. Проиллюстрируем это на простом примере, создадим следующий файл __main__.py :
При его запуске появится такое приветственное сообщение:
Теперь добавим его в ZIP-архив. Это можно сделать в командной строке:
А в Windows для этого можно использовать метод «укажи и щелкни». Выберите файл в «Проводнике», затем нажмите на нём правой кнопкой мыши и выберите Send to (Отправить) → Compressed (zipped) folder (Сжатая (заархивированная) папка).
__main__ — название не слишком информативное, поэтому мы назвали ZIP-файл hello.zip . Теперь можно прямо вызвать его с Python:
Наш скрипт знает, что он находится внутри hello.zip . Более того, корневой каталог нашего ZIP-файла добавляется в путь импорта Python, так что скрипты могут импортировать другие модули внутри одного и того же ZIP-файла.
Вспомним наш пример с созданием викторины, основанной на демографических данных. Можно распространять всё это приложение одним ZIP-файлом. importlib.resources позаботится о том, чтобы файл данных был извлечён из ZIP-архива, когда это потребуется.
Приложение состоит из следующих файлов:
Их можно добавить в ZIP-файл так же, как мы это сделали раньше. Но в Python есть инструмент под названием zipapp , который упрощает процесс упаковывания приложений в ZIP-архивы. Используется он следующим образом:
Что делает эта команда: создает точку входа и упаковывает приложение.
Не будем забывать, что нам нужен файл __main__.py как точка входа в ZIP-архив. Если мы снабдим параметр -m информацией о том, как должно запускаться наше приложение, то zipapp создаст для нас этот файл. В этом примере сгенерированный __main__.py выглядит примерно так:
Этот __main__.py упаковывается вместе с содержимым каталога population_quiz в ZIP-архив с именем population_quiz.pyz . Суффикс .pyz указывает на то, что это файл Python, который помещён в ZIP-архив.
Примечание: по умолчанию zipapp никаких файлов не сжимает. Он лишь упаковывает их в один файл. zipapp может сжать файлы, для этого надо добавить параметр -c .
Однако эта функция доступна только в Python 3.7 и более поздних версиях. Ещё больше узнать о zipapp можно в официальной документации.
В Windows .pyz -файлы уже должны регистрироваться как файлы Python. На Mac и Linux вы можете с помощью zipapp создать исполняемые файлы, задействовав параметр -p интерпретатора и указав, какой интерпретатор использовать:
Параметр -p добавляет последовательность символов ( #! ), которая сообщает операционной системе, как запускать файл. Кроме того, он делает .pyz -файл исполняемым, так что теперь можно запустить файл, просто введя его имя:
Обратите внимание на ./ перед именем файла. Это типичный приём, используемый на Mac и Linux для запуска исполняемых файлов в текущем каталоге. Если вы перемещаете файл в каталог по своему PATH или используете Windows, то имя файла должно быть только таким: population_quiz.pyz .
Замечание: на Python 3.6 и более поздних версиях предыдущая команда завершится с сообщением о том, что ресурс демографических данных в каталоге data найти не удалось. Это связано с ограничением в zipimport .
Решение: добавить к population_quiz.pyz абсолютный путь. На Mac и Linux это можно сделать с помощью такого приёма:
Команда pwd расширяется до пути к текущему каталогу.
В завершение этой часть статьи рассмотрим, как importlib.resources помогают открывать файл данных. Ранее мы уже использовали для этого следующий код:
Более распространенный способ открытия файлов данных — обнаруживать их с помощью атрибута модуля __file__ :
Такой подход обычно хорошо работает. Но даёт сбой, когда приложение упаковывается в ZIP-файл:
Файл данных внутри ZIP-архива, поэтому open() не может его открыть. importlib.resources решает эту проблему: извлекает данные во временный файл и потом открывает его.
Циклический импорт
Циклический импорт происходит, когда имеются два или больше модулей, импортирующих друг друга. Конкретизируем: представьте, что модуль yin использует import yang , а модуль yang аналогично импортирует yin .
В системе импорта Python предусмотрены определённые возможности для работы с циклами импорта. Например, следующий код — хотя и не очень полезный — работает нормально:
При попытке в интерактивном интерпретаторе импортировать yin вместе с ним импортируется и yang :
Обратите внимание: yang импортируется внутри импорта yin , а именно в операторе import yang в исходном коде yin . При этом не происходит бесконечной рекурсии. Не даёт ей случиться наш старый друг, кэш модулей.
Когда мы вводим import yin , ссылка на yin добавляется в кэш модулей ещё до загрузки yin . Когда потом yang пытается импортировать yin , он просто использует эту ссылку в кэше модулей.
Проделайте сами нечто подобное или что-то более толковое с модулями. Если вы в своих модулях определяете атрибуты и функции, всё это по-прежнему работает:
Импорт yin работает так же, как и раньше:
Проблемы с рекурсивным импортом начинают возникать, когда вы фактически используете другой модуль во время импорта, вместо того чтобы просто определять функции, которые впоследствии будут использовать другой модуль. Добавим одну строчку к yang.py :
И тут импорт приводит Python в замешательство:
Появление сообщения об ошибке может показаться на первый взгляд немного странным. Возвращаясь к исходному коду, мы можем убедиться, что number определяется в модуле yin .
Проблема в том, что number не определяется в yin в тот момент, когда импортируется yang . Поэтому yin.number используется вызовом combine() .
Кроме этой проблемы, никаких сложностей при импортировании yang не возникнет:
К тому времени, когда yang вызывает combine() , yin полностью импортируется, а yin.number благополучно определяется. И последний приём: из-за того кэша модулей, который мы видели ранее, import yin может сработать, если сначала будут выполнены другие импорты:
Так как же нам избежать путаницы и не увязнуть в циклическом импорте? Наличие как минимум двух модулей, импортирующих друг друга, часто свидетельствует о том, что можно улучшить структуру модулей.
Часто решить проблему циклического импорта проще всего до момента его реализации. Если вы видите циклы в своих упрощённых структурах, присмотритесь повнимательнее и попробуйте разорвать эти циклы.
Тем не менее бывает целесообразно оставить цикл импорта. Как мы уже видели, это не проблема, пока модули определяют только атрибуты, функции, классы и так далее. Второй совет (тоже хорошая структурная практика) — предохранять модули от побочных эффектов во время импорта.
Если уж вам так нужны модули с циклами импорта и побочными эффектами, есть ещё один выход: выполняйте импорт локально внутри функций.
Обратите внимание: в следующем коде import yang выполняется внутри combine() . Из этого следует, что yang доступен только внутри функции combine() . А главное — импорт не выполняется до тех пор, пока вы не вызовете combine() после того, как yin будет полностью импортирован:
Теперь нет никаких проблем при импортировании и использовании yin :
Посмотрите: yang фактически не импортируется, пока не вызывается combine() . Другой взгляд на циклический импорт представлен в работе Fredrik Lundh’s classic note (eng).
Профиль импорта
Одна из проблем при импорте нескольких модулей и пакетов состоит в том, что это увеличивает время запуска скрипта. В зависимости от приложения она может быть критичной или некритичной.
С момента выхода Python 3.7 у нас появился быстрый способ узнать, сколько времени занимает импорт пакетов и модулей. Python 3.7 поддерживает параметр командной строки -X importtime , благодаря которому замеряется и выводится на экран время, уходящее на импортирование каждого модуля:
В столбце cumulative показано совокупное время импорта (в микросекундах) каждого пакета. Можно прочитать этот список следующим образом: Python потратил 1320 микросекунд, чтобы полностью импортировать datetime , в том числе выполнить импорт time , math , а также реализации C _datetime .
Столбец self показывает время, затраченное на импорт только данного модуля, исключая любой рекурсивный импорт. Как видите, на импорт time потребовалось 87 микросекунд, на импорт math ушло 180 , а на _datetime было затрачено 234 . Импорт самого datetime занял 820 микросекунд. Совокупное время в итоге составило 1320 микросекунд (с учётом погрешности округления).
Взгляните на пример countdown.py с Colorama, который был приведён чуть выше в этой статье:
В этом примере импортирование optional_color заняло почти 0,013 секунды. Большая часть этого времени была потрачена на импорт Colorama и её зависимостей. В столбце self показано время импорта без учета вложенного импорта.
Для контраста рассмотрим пример с синглтоном численности населения из первой части статьи. Загружать приходится большой файл данных, поэтому его импорт происходит очень медленно. Проверим это, запустив import population в качестве скрипта с параметром -c :
Здесь импорт population занимает почти 2 секунды, из которых около 1,6 секунды тратятся в самом модуле, в основном на загрузку файла данных.
-X importtime — это отличный инструмент для оптимизации импорта. Если вам нужен более общий мониторинг и оптимизация кода, ознакомьтесь со статьёй Python Timer Functions: Three Ways to Monitor Your Code (eng).
Заключение
В этой статье мы познакомились с системой импорта Python. Как и многое другое, что есть в Python, она довольно проста в использовании для выполнения базовых задач, таких как импорт модулей и пакетов. В то же время система импорта достаточно сложная, гибкая и расширяемая. Мы с вами узнали ряд приёмов и особенностей, связанных с импортом, которые можно использовать в своём собственном коде.
Из этой статьи мы узнали, как:
- создавать пакеты пространства имён;
- импортировать ресурсы и файлы данных;
- определять, что импортировать динамически во время выполнения;
- расширять систему импорта Python;
- работать с разными версиями пакетов.
На протяжении всей статьи мы видели много ссылок на дополнительную информацию. Наиболее авторитетным источником по системе импорта Python является официальная документация:
-
(eng). importlib (eng). (eng). (eng).
Теперь мы можем применять на практике полученные знания об импорте Python, следуя примерам этой статьи. Нажмите на ссылку ниже, чтобы перейти к исходному коду:
Получить исходный код: Нажмите здесь и получите исходный код, используемый для изучения системы импорта Python в этой статье.
Импортирование модулей в Python

В Пайтоне имеется большое количество заранее написанных кодов, которые также известны как модули и пакеты. Модуль – это один файл, импортируемый Пайтоном, в то время как пакет состоит из двух и более модулей. Пакеты импортируются таким же образом, как и модули. Каждый сохраненный вами скрипт в Пайтоне является модулем. Это, конечно, может быть далеко не самым полезным модулем, но тем не менее. В данном разделе мы рассмотрим, как импортировать модули при помощи нескольких различных методов.
Импортируем модуль «this»
В Пайтоне есть ключевые слова для импорта модулей. Попробуйте вот этот:
Запустив данный код в своем интерпретаторе, вы увидите что-то в таком духе:
Поздравляем, вы нашли «пасхальное яйцо» в Пайтоне, также известное как «Дзен». Это одна из лучших неофициальных частей работы в Пайтон. Сам по себе модуль this не делает ничего особенного, только показывает оригинальный способ импорта чего-либо. Теперь давайте импортируем что-нибудь, чем мы сможем воспользоваться в будущем, к примеру, модуль math:
В примере выше мы импортировали модуль math и сделали что-то новое. Мы вызвали одну из функций модуля – sqrt (т.е. square root – квадратный корень). Для вызова метода импортированного модуля, нам нужно использовать следующий синтаксис: module_name.method_name(аргумент). В данном примере мы нашли квадратный корень от 4. В модуле math есть много других функций, которыми мы можем воспользоваться, такие как нахождение косинуса, факториал, логарифмы и другие. Вы можете призывать эти функции таким же образом, как и с функцией sqrt. Единственное, в чем вам нужно удостовериться – принимают ли они большее количество аргументов или нет. Теперь посмотрим на другой способ импорта.
Использование from в импорте
Некоторые люди не очень любят обозначать все, что они пишут названиями модулей. Впрочем, в Пайтоне есть решение и для этого. Вы можете импортировать из модуля только те функции, которые вам нужны. Представим, что нам нужно импортировать только функцию sqrt:
Это работает именно так, как читается: функция sqrt импортируется из модуля math. Попробую объяснить это иначе. Мы использовали ключевое слово from для импорта функции sqrt из модуля math. Мы также можем использовать этот метод для импорта нескольких функций из модуля math:
В данном примере мы импортировали как sqrt так и pi. Перед тем как обратиться к pi, стоит обратить внимание на то, что это не функция, которую вы вызываете, а величина.
Заказать дешевых подписчиков в группу ВК с качественными страницами можно на сервисе https://doctorsmm.com/. Вам также будет предложен широкий выбор формата ресурса и скорости его поступления. Обратите внимание, что практически на каждую услугу действуют внушительные оптовые скидки и гарантии. Не упустите свое выгодное предложение!
Когда вы выполняете импорт, вы действительно можете сделать это с величинами, функциями, даже с другим модулем. Есть еще один способ импорта, на который стоит обратить внимание. Давайте импортируем вообще всё!
Есть вопросы по Python?
На нашем форуме вы можете задать любой вопрос и получить ответ от всего нашего сообщества!
Telegram Чат & Канал
Вступите в наш дружный чат по Python и начните общение с единомышленниками! Станьте частью большого сообщества!
Паблик VK
Одно из самых больших сообществ по Python в социальной сети ВК. Видео уроки и книги для вас!
Импорт всего
В Пайтоне предусмотрена возможность импорта всех функций, переменных и модулей за раз. Это может быть плохой идеей, так как такой импорт может засорить ваше пространство имен. Пространство имен – это место, в котором находятся все ваши переменные, пока работает программа. К примеру, у вас есть своя переменная под названием sqrt:
Только что вы сделали функцию sqrt переменной, значение которой 5. Это называется затенением (shadowing). Это особенно хитрый способ упрощения своей жизни, когда вы выполняете импорт всего из модуля. Давайте взглянем:
Для импорта всего, кроме определенных частей модуля, мы просто используем знак * , что означает, что нам нужно импортировать все. В случае если мы не знаем, что находится в модуле math, мы даже не поймем, что уничтожили одну из импортированных функций. Когда мы пытаемся вызвать функцию sqrt после присвоения её целому числу, мы обнаружим, что она больше не работает.
По этой причине, в большинстве случаев рекомендуется использовать один из указанных в данном разделе способов для импорта. Но есть и несколько исключений из этого правила. В некоторых модулях импорт предусмотрен заранее, это возможно благодаря методу “*”. Одним из ярких примеров является Tkinter – набор инструментов, работающий с Пайтоном, который позволяет пользователю создавать пользовательские интерфейсы на рабочем столе. Причина, по которой определенно удобно импортировать через Tkinter заключается в том, что модули все имеют имена, так что вероятность повторного использования стремится к нулю.
Подведем итоги
Теперь вы знаете все об импорте в Пайтоне. Существуют десятки модулей, которые включены в Пайтон и которые вы можете применять для поднятия функционала своих программ. Вы можете использовать встроенные модули для запросов ОС, получить информацию из реестра Windows, настроить утилиты ведения журнала, выполнять анализ XML и многое, многое другое.

Являюсь администратором нескольких порталов по обучению языков программирования Python, Golang и Kotlin. В составе небольшой команды единомышленников, мы занимаемся популяризацией языков программирования на русскоязычную аудиторию. Большая часть статей была адаптирована нами на русский язык и распространяется бесплатно.