Отражение не поддерживается C ++ из коробки. Это печально, потому что это делает защитное испытание болью.
Существует несколько подходов к отражению:
Первая ссылка выглядит наиболее многообещающий (использует mod's to clang), второй обсуждает ряд методов, третий - другой подход с использованием gcc:
В настоящее время существует рабочая группа для отражения C ++. См. Новости для C ++ 14 @ CERN:
Редактировать 13/08/17: Поскольку исходный пост имел ряд потенциальных улучшений в отношении отражения. Ниже приводится более подробная информация и обсуждение различных методов и статуса:
Однако в ближайшем будущем это не выглядит многообещающим по стандартизованному методу отражения в C ++ если в сообществе больше интереса к поддержке для размышлений на C ++.
Ниже приводится информация о текущем состоянии, основанном на обратной связи с последними встречами на C ++:
Редактировать 13/12/2017
Отражение похоже на перемещение к C ++ 20 или, более вероятно, к TSR.
import socket
socket.gethostbyname(socket.gethostname())
Это не будет всегда работать (возвраты 127.0.0.1
на машинах, имеющих имя узла в /etc/hosts
как 127.0.0.1
), паллиатив был бы тем, что показывает gimel, используйте socket.getfqdn()
вместо этого. Конечно, Вашей машине нужно разрешимое имя узла.
Если Вы не хотите использовать внешние пакеты и не хотите полагаться на внешние Интернет-серверы, это могло бы помочь. Это - пример кода, который я нашел на Google Code Search и изменил для возврата запрошенной информации:
def getIPAddresses():
from ctypes import Structure, windll, sizeof
from ctypes import POINTER, byref
from ctypes import c_ulong, c_uint, c_ubyte, c_char
MAX_ADAPTER_DESCRIPTION_LENGTH = 128
MAX_ADAPTER_NAME_LENGTH = 256
MAX_ADAPTER_ADDRESS_LENGTH = 8
class IP_ADDR_STRING(Structure):
pass
LP_IP_ADDR_STRING = POINTER(IP_ADDR_STRING)
IP_ADDR_STRING._fields_ = [
("next", LP_IP_ADDR_STRING),
("ipAddress", c_char * 16),
("ipMask", c_char * 16),
("context", c_ulong)]
class IP_ADAPTER_INFO (Structure):
pass
LP_IP_ADAPTER_INFO = POINTER(IP_ADAPTER_INFO)
IP_ADAPTER_INFO._fields_ = [
("next", LP_IP_ADAPTER_INFO),
("comboIndex", c_ulong),
("adapterName", c_char * (MAX_ADAPTER_NAME_LENGTH + 4)),
("description", c_char * (MAX_ADAPTER_DESCRIPTION_LENGTH + 4)),
("addressLength", c_uint),
("address", c_ubyte * MAX_ADAPTER_ADDRESS_LENGTH),
("index", c_ulong),
("type", c_uint),
("dhcpEnabled", c_uint),
("currentIpAddress", LP_IP_ADDR_STRING),
("ipAddressList", IP_ADDR_STRING),
("gatewayList", IP_ADDR_STRING),
("dhcpServer", IP_ADDR_STRING),
("haveWins", c_uint),
("primaryWinsServer", IP_ADDR_STRING),
("secondaryWinsServer", IP_ADDR_STRING),
("leaseObtained", c_ulong),
("leaseExpires", c_ulong)]
GetAdaptersInfo = windll.iphlpapi.GetAdaptersInfo
GetAdaptersInfo.restype = c_ulong
GetAdaptersInfo.argtypes = [LP_IP_ADAPTER_INFO, POINTER(c_ulong)]
adapterList = (IP_ADAPTER_INFO * 10)()
buflen = c_ulong(sizeof(adapterList))
rc = GetAdaptersInfo(byref(adapterList[0]), byref(buflen))
if rc == 0:
for a in adapterList:
adNode = a.ipAddressList
while True:
ipAddr = adNode.ipAddress
if ipAddr:
yield ipAddr
adNode = adNode.next
if not adNode:
break
Использование:
>>> for addr in getIPAddresses():
>>> print addr
192.168.0.100
10.5.9.207
, Поскольку это полагается windll
, это будет работать только над Windows.
Можно использовать модуль netifaces . Просто введите:
pip install netifaces
в Вашем командном процессоре и это установит себя на установке Python по умолчанию.
Тогда можно использовать его как это:
from netifaces import interfaces, ifaddresses, AF_INET
for ifaceName in interfaces():
addresses = [i['addr'] for i in ifaddresses(ifaceName).setdefault(AF_INET, [{'addr':'No IP addr'}] )]
print '%s: %s' % (ifaceName, ', '.join(addresses))
На моем компьютере это распечатало:
{45639BDC-1050-46E0-9BE9-075C30DE1FBC}: 192.168.0.100 {D43A468B-F3AE-4BF9-9391-4863A4500583}: 10.5.9.207
Автор этого модуля утверждает, что он должен работать над Windows, UNIX и Mac OS X.
Я боюсь, что нет никаких хороших независимых от платформы способов сделать, это кроме соединения с другим компьютером и наличия его отправляет Вам Ваш IP-адрес. Например: findmyipaddress. Обратите внимание, что это не будет работать при необходимости в IP-адресе, это находится позади NAT, если компьютер, с которым Вы соединяетесь, не находится позади NAT также.
Вот одно решение, которое работает в Linux: связали IP-адрес с сетевым интерфейсом .
Я просто нашел это, но это кажется небольшим hackish, однако они говорят, примерил его *, отклоняют, и я сделал на окнах, и это работало.
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
print(s.getsockname()[0])
s.close()
Это предполагает, что у Вас есть доступ в Интернет, и что нет никакого локального прокси.
Как псевдоним myip
, он должен работать везде:
alias myip="python -c 'import socket; print([l for l in ([ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith(\"127.\")][:1], [[(s.connect((\"8.8.8.8\", 53)), s.getsockname()[0], s.close()) for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1]]) if l][0][0])'"
То же, что и выше, но только код Python :
import socket
print([l for l in ([ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith("127.")][:1], [[(s.connect(('8.8.8.8', 53)), s.getsockname()[0], s.close()) for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1]]) if l][0][0])
Версия, которая также будет работать в локальных сетях без подключения к Интернету:
import socket
print((([ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith("127.")] or [[(s.connect(("8.8.8.8", 53)), s.getsockname()[0], s.close()) for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1]]) + ["no IP found"])[0])
(спасибо @ccpizza )
Фон :
Использование socket.gethostbyname (socket.gethostname ())
здесь не сработало, потому что на одном из компьютеров, на которых я был, был / etc / hosts
с дубликатом записи и ссылки на себя. розетка. gethostbyname ()
возвращает только последнюю запись в / etc / hosts
.
Это была моя первая попытка отсеять все адреса, начинающиеся с «127.»
:
import socket
print([ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith("127.")][:1])
Это работает с Python 2 и 3, в Linux и Windows, но не работает с несколькими сетевыми устройствами или IPv6. Однако он перестал работать в последних дистрибутивах Linux, поэтому вместо этого я попробовал эту альтернативную технику. Он пытается подключиться к DNS-серверу Google по адресу 8.8.8.8
через порт 53
:
import socket
print([(s.connect(('8.8.8.8', 53)), s.getsockname()[0], s.close()) for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1])
Затем я объединил два вышеуказанных метода в однострочник, который должен работать везде, и создал псевдоним myip
и фрагмент кода Python в верхней части этого ответа.
С ростом популярности IPv6 и для серверов с несколькими сетевыми интерфейсами,
im, используя следующий модуль:
#!/usr/bin/python
# module for getting the lan ip address of the computer
import os
import socket
if os.name != "nt":
import fcntl
import struct
def get_interface_ip(ifname):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
return socket.inet_ntoa(fcntl.ioctl(
s.fileno(),
0x8915, # SIOCGIFADDR
struct.pack('256s', bytes(ifname[:15], 'utf-8'))
# Python 2.7: remove the second argument for the bytes call
)[20:24])
def get_lan_ip():
ip = socket.gethostbyname(socket.gethostname())
if ip.startswith("127.") and os.name != "nt":
interfaces = ["eth0","eth1","eth2","wlan0","wlan1","wifi0","ath0","ath1","ppp0"]
for ifname in interfaces:
try:
ip = get_interface_ip(ifname)
break;
except IOError:
pass
return ip
Tested with windows and linux (и не требует дополнительных модулей для них) предназначенный для использования на системах, которые находятся в одной локальной сети, основанной на IPv4.
Фиксированный список имен интерфейсов не работает для последних версий linux, которые приняли изменение systemd v197 относительно предсказуемых имен интерфейсов, на что указывает Александр. В таких случаях вам необходимо вручную заменить список имен интерфейсов на имена интерфейсов в вашей системе, или использовать другое решение, например, netifaces.
.FYI Я могу проверить, что метод:
import socket
addr = socket.gethostbyname(socket.gethostname())
работает в OS X (10.6,10.5), Windows XP, и на хорошо администрируемом сервере отдела RHEL. Он не работает на очень минимальной ВМ CentOS, на которой я просто делаю некоторые взломы ядра. Так что для этого случая можно просто проверить адрес 127.0.0.1 и в этом случае сделать следующее:
if addr == "127.0.0.1":
import commands
output = commands.getoutput("/sbin/ifconfig")
addr = parseaddress(output)
А затем разобрать ip-адрес из выходных данных. Следует отметить, что ifconfig по умолчанию не находится в PATH обычного пользователя, и поэтому я указываю полный путь в команде. Надеюсь, это поможет.
Я использую это на своих машинах с Ubuntu:
import commands
commands.getoutput("/sbin/ifconfig").split("\n")[1].split()[1][5:]
Это не работает.
Для Linux можно просто использовать check_output
из hostname -I
системная команда как так:
from subprocess import check_output
check_output(['hostname', '-I'])