Импортирование ошибки при импорте модуля, который импортирует другие модули с помощью python3, но нет с python 2.x [duplicate]

Вот простой один вкладыш

$ip = $_SERVER['HTTP_X_FORWARDED_FOR']?: $_SERVER['HTTP_CLIENT_IP']?: $_SERVER['REMOTE_ADDR'];

EDIT:

Выше код может возвращать зарезервированные адреса (например, 10.0.0.1), список адресов всех прокси-серверов на пути и т. д. Для обработки этих случаев используйте следующий код:

function valid_ip($ip) {
    // for list of reserved IP addresses, see https://en.wikipedia.org/wiki/Reserved_IP_addresses
    return $ip && substr($ip, 0, 4) != '127.' && substr($ip, 0, 4) != '127.' && substr($ip, 0, 3) != '10.' && substr($ip, 0, 2) != '0.' ? $ip : false;
}

function get_client_ip() {
    // using explode to get only client ip from list of forwarders. see https://en.wikipedia.org/wiki/X-Forwarded-For
    return
    @$_SERVER['HTTP_X_FORWARDED_FOR'] ? explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'], 2)[0] :
    @$_SERVER['HTTP_CLIENT_IP'] ? explode(',', $_SERVER['HTTP_CLIENT_IP'], 2)[0] :
    valid_ip(@$_SERVER['REMOTE_ADDR']) ?:
    'UNKNOWN';
}

echo get_client_ip();

122
задан balki 29 August 2012 в 08:24
поделиться

4 ответа

Относительный импорт происходит всякий раз, когда вы импортируете пакет относительно текущего скрипта / пакета.

Рассмотрим следующее дерево, например:

mypkg
├── base.py
└── derived.py

Теперь ваш derived.py требует что-то из base.py. В Python 2 вы можете сделать это так (в derived.py):

from base import BaseThing

Python 3 больше не поддерживает это, поскольку он не является явным, хотите ли вы «относительного» или «абсолютного» base. Другими словами, если в системе был установлен пакет Python с именем base, вы бы ошибались.

Вместо этого он требует, чтобы вы использовали явный импорт , который явно указать расположение модуля на основе пути. Ваш derived.py будет выглядеть так:

from .base import BaseThing

Ведущий . говорит «import base из каталога модуля»; Другими словами, .base отображается на ./base.py.

Аналогичным образом существует префикс .., который поднимается вверх по иерархии каталогов, такой как ../..mod отображением на ../mod.py), и затем ..., который идет на два уровня вверх (../../mod.py) и т. д.

Пожалуйста, обратите внимание, что относительные пути, перечисленные выше, относились к каталогу, в котором находится текущий модуль (derived.py), не текущий рабочий каталог.


@BrenBarn уже объяснил случай импорта звезды. Для полноты, я должен будет сказать то же самое;).

Например, вам нужно использовать несколько функций math, но вы используете их только в одной функции. В Python 2 вам разрешили быть полу-ленивым:

def sin_degrees(x):
    from math import *
    return sin(degrees(x))

Обратите внимание, что он уже запускает предупреждение в Python 2:

a.py:1: SyntaxWarning: import * only allowed at module level
  def sin_degrees(x):

В современном коде Python 2 вы должны и в Python 3 вы должны сделать либо:

def sin_degrees(x):
    from math import sin, degrees
    return sin(degrees(x))

, либо:

from math import *

def sin_degrees(x):
    return sin(degrees(x))
199
ответ дан mloskot 19 August 2018 в 06:00
поделиться

Чтобы поддерживать как Python 2, так и Python 3, используйте явно относительный импорт, как показано ниже. Они относятся к текущему модулю. Они поддерживаются , начиная с 2.5 .

from .sister import foo
import .brother
from ..aunt import bar
import ..uncle
3
ответ дан Akseli Palén 19 August 2018 в 06:00
поделиться

Для относительного импорта см. документацию . Относительный импорт - это когда вы импортируете из модуля относительно местоположения этого модуля, а не абсолютно из sys.path.

Что касается import *, Python 2 допускал импорт звезд внутри функций, например:

>>> def f():
...     from math import *
...     print sqrt

Предупреждение выдается для этого в Python 2 (по крайней мере, в последних версиях). В Python 3 это больше не разрешено, и вы можете только импортировать звезды на верхнем уровне модуля (не внутри функций или классов).

10
ответ дан BrenBarn 19 August 2018 в 06:00
поделиться
  • 1
    Надеюсь, вы не против, опираясь на ваш пример;). – Michał Górny 29 August 2012 в 09:10
  • 2
    Почему это решение было принято? – Dor 22 November 2013 в 11:29
  • 3
    Я предполагаю, что идея заключается в том, что «Явный лучше, чем неявный». от PEP20 - Zen of Python. Точка перед модулем делает относительную / неродственную связь явной, таким образом разрешая возможные столкновения имен. Хотя «Чтение учитывается». немного страдает. – Pafnucy 3 September 2015 в 11:01
  • 4
    Нет, на самом деле это была «противоположная», «практичность превосходит чистоту». решение. Это было необходимо для оптимизации локального доступа к переменной внутри функций, поскольку без «import *» компилятор всегда знает, просто анализируя код, какие переменные являются локальными и могут быть просмотрены напрямую. На самом деле, функции даже не используют dict для локального хранилища, а оптимизированный массив, где переменные получают уникальные индексы. – Veky 24 September 2015 в 11:06

Добавил еще один ответ на вопрос Михаила Горни:

Обратите внимание, что относительный импорт основан на имени текущего модуля. Поскольку имя основного модуля всегда «основное», модули, предназначенные для использования в качестве основного модуля приложения Python, должны всегда использовать абсолютный импорт.

0
ответ дан Panfeng Li 19 August 2018 в 06:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: