- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试在 Python Google Appengine 上进行一些 IP 查找,如下所示:
import pygeoip
gi = pygeoip.GeoIP('GeoIP.dat')
Location = gi.country_code_by_addr(self.request.remote_addr)
(pygeoip可以在这里找到:http://code.google.com/p/pygeoip/)
上面的代码在本地执行得很好,但是当我将其推送到实时服务器时,出现以下错误:
<type 'exceptions.ImportError'>: No module named mmap
Traceback (most recent call last):
File "/base/data/home/apps/tomcritchlow1/geoip.347423765058502279/main.py", line 28, in <module>
import pygeoip
File "/base/data/home/apps/tomcritchlow1/geoip.347423765058502279/pygeoip/__init__.py", line 34, in <module>
import mmap
我在本地使用 Python 2.5,所以它应该与我认为的实时服务器相同?
Pygeoip 页面内容如下:
Supported Flags:
STANDARD (do all reads from disk, slowest)
MEMORY_CACHE
MMAP_CACHE (map the whole file to memory, fastest)
我不确定“支持的标志”到底是什么意思 - 如果 mmap 是问题所在,我可以使用内存缓存而不是 mmap 来使用 Pygeoip 吗?我该怎么做?
谢谢!
汤姆
PS - 仍然是 n00b 编码,所以请放轻松:)
编辑:
下面概述的解决方案有效,首先使用此代码:
gi = pygeoip.GeoIP('GeoIP.dat', flags=pygeoip.const.MEMORY_CACHE)
然后修改 pygeoip 中的 init.py 文件,如下所示(警告!我只是注释掉了一些代码,没有做任何花哨的事情!!)
"""
Pure Python GeoIP API. The API is based off of U{MaxMind's C-based Python API<http://www.maxmind.com/app/python>},
but the code itself is based on the U{pure PHP5 API<http://pear.php.net/package/Net_GeoIP/>}
by Jim Winstead and Hans Lellelid.
It is mostly a drop-in replacement, except the
C{new} and C{open} methods are gone. You should instantiate the L{GeoIP} class yourself:
C{gi = GeoIP('/path/to/GeoIP.dat', pygeoip.MEMORY_CACHE)}
@author: Jennifer Ennis <zaylea at gmail dot com>
@license:
Copyright(C) 2004 MaxMind LLC
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/lgpl.txt>.
"""
from __future__ import with_statement
import os
import math
import socket
#import mmap
from const import *
from util import ip2long
class GeoIPError(Exception):
pass
class GeoIPMetaclass(type):
def __new__(cls, *args, **kwargs):
"""
Singleton method to gets an instance without reparsing the db. Unique
instances are instantiated based on the filename of the db. Flags are
ignored for this, i.e. if you initialize one with STANDARD flag (default)
and then try later to initialize with MEMORY_CACHE, it will still
return the STANDARD one.
"""
if not hasattr(cls, '_instances'):
cls._instances = {}
if len(args) > 0:
filename = args[0]
elif 'filename' in kwargs:
filename = kwargs['filename']
if not filename in cls._instances:
cls._instances[filename] = type.__new__(cls, *args, **kwargs)
return cls._instances[filename]
GeoIPBase = GeoIPMetaclass('GeoIPBase', (object,), {})
class GeoIP(GeoIPBase):
def __init__(self, filename, flags=0):
"""
Initialize the class.
@param filename: path to a geoip database
@type filename: str
@param flags: flags that affect how the database is processed.
Currently the only supported flags are STANDARD, MEMORY_CACHE, and
MMAP_CACHE.
@type flags: int
"""
self._filename = filename
self._flags = flags
#tom:
#if self._flags & MMAP_CACHE:
if '2' == '3':
with open(filename, 'rb') as f:
self._filehandle = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
else:
self._filehandle = open(filename, 'rb')
#tom:
#if self._flags & MEMORY_CACHE:
# self._memoryBuffer = self._filehandle.read()
self._setup_segments()
def _setup_segments(self):
"""
Parses the database file to determine what kind of database is being used and setup
segment sizes and start points that will be used by the seek*() methods later.
"""
self._databaseType = COUNTRY_EDITION
self._recordLength = STANDARD_RECORD_LENGTH
filepos = self._filehandle.tell()
self._filehandle.seek(-3, os.SEEK_END)
for i in range(STRUCTURE_INFO_MAX_SIZE):
delim = self._filehandle.read(3)
if delim == (chr(255) * 3):
self._databaseType = ord(self._filehandle.read(1))
if (self._databaseType >= 106):
# backwards compatibility with databases from April 2003 and earlier
self._databaseType -= 105
if self._databaseType == REGION_EDITION_REV0:
self._databaseSegments = STATE_BEGIN_REV0
elif self._databaseType == REGION_EDITION_REV1:
self._databaseSegments = STATE_BEGIN_REV1
elif self._databaseType in (CITY_EDITION_REV0,
CITY_EDITION_REV1,
ORG_EDITION,
ISP_EDITION,
ASNUM_EDITION):
self._databaseSegments = 0
buf = self._filehandle.read(SEGMENT_RECORD_LENGTH)
for j in range(SEGMENT_RECORD_LENGTH):
self._databaseSegments += (ord(buf[j]) << (j * 8))
if self._databaseType in (ORG_EDITION, ISP_EDITION):
self._recordLength = ORG_RECORD_LENGTH
break
else:
self._filehandle.seek(-4, os.SEEK_CUR)
if self._databaseType == COUNTRY_EDITION:
self._databaseSegments = COUNTRY_BEGIN
self._filehandle.seek(filepos, os.SEEK_SET)
def _lookup_country_id(self, addr):
"""
Get the country index.
This method is called by the _lookupCountryCode and _lookupCountryName
methods. It looks up the index ('id') for the country which is the key
for the code and name.
@param addr: The IP address
@type addr: str
@return: network byte order 32-bit integer
@rtype: int
"""
ipnum = ip2long(addr)
if not ipnum:
raise ValueError("Invalid IP address: %s" % addr)
if self._databaseType != COUNTRY_EDITION:
raise GeoIPError('Invalid database type; country_* methods expect '\
'Country database')
return self._seek_country(ipnum) - COUNTRY_BEGIN
def _seek_country(self, ipnum):
"""
Using the record length and appropriate start points, seek to the
country that corresponds to the converted IP address integer.
@param ipnum: result of ip2long conversion
@type ipnum: int
@return: offset of start of record
@rtype: int
"""
offset = 0
for depth in range(31, -1, -1):
#tom:
#if self._flags & MEMORY_CACHE:
if '2' == '3':
startIndex = 2 * self._recordLength * offset
length = 2 * self._recordLength
endIndex = startIndex + length
buf = self._memoryBuffer[startIndex:endIndex]
else:
self._filehandle.seek(2 * self._recordLength * offset, os.SEEK_SET)
buf = self._filehandle.read(2 * self._recordLength)
x = [0,0]
for i in range(2):
for j in range(self._recordLength):
x[i] += ord(buf[self._recordLength * i + j]) << (j * 8)
if ipnum & (1 << depth):
if x[1] >= self._databaseSegments:
return x[1]
offset = x[1]
else:
if x[0] >= self._databaseSegments:
return x[0]
offset = x[0]
raise Exception('Error traversing database - perhaps it is corrupt?')
def _get_org(self, ipnum):
"""
Seek and return organization (or ISP) name for converted IP addr.
@param ipnum: Converted IP address
@type ipnum: int
@return: org/isp name
@rtype: str
"""
seek_org = self._seek_country(ipnum)
if seek_org == self._databaseSegments:
return None
record_pointer = seek_org + (2 * self._recordLength - 1) * self._databaseSegments
self._filehandle.seek(record_pointer, os.SEEK_SET)
org_buf = self._filehandle.read(MAX_ORG_RECORD_LENGTH)
return org_buf[:org_buf.index(chr(0))]
def _get_region(self, ipnum):
"""
Seek and return the region info (dict containing country_code and region_name).
@param ipnum: converted IP address
@type ipnum: int
@return: dict containing country_code and region_name
@rtype: dict
"""
country_code = ''
region = ''
if self._databaseType == REGION_EDITION_REV0:
seek_country = self._seek_country(ipnum)
seek_region = seek_country - STATE_BEGIN_REV0
if seek_region >= 1000:
country_code = 'US'
region = ''.join([chr((seek_region / 1000) / 26 + 65), chr((seek_region / 1000) % 26 + 65)])
else:
country_code = COUNTRY_CODES[seek_region]
region = ''
elif self._databaseType == REGION_EDITION_REV1:
seek_country = self._seek_country(ipnum)
seek_region = seek_country - STATE_BEGIN_REV1
if seek_region < US_OFFSET:
country_code = '';
region = ''
elif seek_region < CANADA_OFFSET:
country_code = 'US'
region = ''.join([chr((seek_region - US_OFFSET) / 26 + 65), chr((seek_region - US_OFFSET) % 26 + 65)])
elif seek_region < WORLD_OFFSET:
country_code = 'CA'
region = ''.join([chr((seek_region - CANADA_OFFSET) / 26 + 65), chr((seek_region - CANADA_OFFSET) % 26 + 65)])
else:
i = (seek_region - WORLD_OFFSET) / FIPS_RANGE
if i in COUNTRY_CODES:
country_code = COUNTRY_CODES[(seek_region - WORLD_OFFSET) / FIPS_RANGE]
else:
country_code = ''
region = ''
elif self._databaseType in (CITY_EDITION_REV0, CITY_EDITION_REV1):
rec = self._get_record(ipnum)
country_code = rec['country_code']
region = rec['region_name']
return {'country_code' : country_code, 'region_name' : region }
def _get_record(self, ipnum):
"""
Populate location dict for converted IP.
@param ipnum: converted IP address
@type ipnum: int
@return: dict with country_code, country_code3, country_name,
region, city, postal_code, latitude, longitude,
dma_code, metro_code, area_code, region_name, time_zone
@rtype: dict
"""
seek_country = self._seek_country(ipnum)
if seek_country == self._databaseSegments:
return None
record_pointer = seek_country + (2 * self._recordLength - 1) * self._databaseSegments
self._filehandle.seek(record_pointer, os.SEEK_SET)
record_buf = self._filehandle.read(FULL_RECORD_LENGTH)
record = {}
record_buf_pos = 0
char = ord(record_buf[record_buf_pos])
record['country_code'] = COUNTRY_CODES[char]
record['country_code3'] = COUNTRY_CODES3[char]
record['country_name'] = COUNTRY_NAMES[char]
record_buf_pos += 1
str_length = 0
# get region
char = ord(record_buf[record_buf_pos+str_length])
while (char != 0):
str_length += 1
char = ord(record_buf[record_buf_pos+str_length])
if str_length > 0:
record['region_name'] = record_buf[record_buf_pos:record_buf_pos+str_length]
record_buf_pos += str_length + 1
str_length = 0
# get city
char = ord(record_buf[record_buf_pos+str_length])
while (char != 0):
str_length += 1
char = ord(record_buf[record_buf_pos+str_length])
if str_length > 0:
record['city'] = record_buf[record_buf_pos:record_buf_pos+str_length]
record_buf_pos += str_length + 1
str_length = 0
# get the postal code
char = ord(record_buf[record_buf_pos+str_length])
while (char != 0):
str_length += 1
char = ord(record_buf[record_buf_pos+str_length])
if str_length > 0:
record['postal_code'] = record_buf[record_buf_pos:record_buf_pos+str_length]
else:
record['postal_code'] = None
record_buf_pos += str_length + 1
str_length = 0
latitude = 0
longitude = 0
for j in range(3):
char = ord(record_buf[record_buf_pos])
record_buf_pos += 1
latitude += (char << (j * 8))
record['latitude'] = (latitude/10000.0) - 180.0
for j in range(3):
char = ord(record_buf[record_buf_pos])
record_buf_pos += 1
longitude += (char << (j * 8))
record['longitude'] = (longitude/10000.0) - 180.0
if self._databaseType == CITY_EDITION_REV1:
dmaarea_combo = 0
if record['country_code'] == 'US':
for j in range(3):
char = ord(record_buf[record_buf_pos])
record_buf_pos += 1
dmaarea_combo += (char << (j*8))
record['dma_code'] = int(math.floor(dmaarea_combo/1000))
record['area_code'] = dmaarea_combo%1000
else:
record['dma_code'] = 0
record['area_code'] = 0
return record
def country_code_by_addr(self, addr):
"""
Returns 2-letter country code (e.g. 'US') for specified IP address.
Use this method if you have a Country, Region, or City database.
@param addr: IP address
@type addr: str
@return: 2-letter country code
@rtype: str
"""
try:
if self._databaseType == COUNTRY_EDITION:
country_id = self._lookup_country_id(addr)
return COUNTRY_CODES[country_id]
elif self._databaseType in (REGION_EDITION_REV0, REGION_EDITION_REV1,
CITY_EDITION_REV0, CITY_EDITION_REV1):
return self.region_by_addr(addr)['country_code']
else:
raise GeoIPError('Invalid database type; country_* methods expect '\
'Country, City, or Region database')
except ValueError:
raise GeoIPError('*_by_addr methods only accept IP addresses. Use *_by_name for hostnames. (Address: %s)' % addr)
def country_code_by_name(self, hostname):
"""
Returns 2-letter country code (e.g. 'US') for specified hostname.
Use this method if you have a Country, Region, or City database.
@param hostname: host name
@type hostname: str
@return: 2-letter country code
@rtype: str
"""
addr = socket.gethostbyname(hostname)
return self.country_code_by_addr(addr)
def country_name_by_addr(self, addr):
"""
Returns full country name for specified IP address.
Use this method if you have a Country or City database.
@param addr: IP address
@type addr: str
@return: country name
@rtype: str
"""
try:
if self._databaseType == COUNTRY_EDITION:
country_id = self._lookup_country_id(addr)
return COUNTRY_NAMES[country_id]
elif self._databaseType in (CITY_EDITION_REV0, CITY_EDITION_REV1):
return self.record_by_addr(addr)['country_name']
else:
raise GeoIPError('Invalid database type; country_* methods expect '\
'Country or City database')
except ValueError:
raise GeoIPError('*_by_addr methods only accept IP addresses. Use *_by_name for hostnames. (Address: %s)' % addr)
def country_name_by_name(self, hostname):
"""
Returns full country name for specified hostname.
Use this method if you have a Country database.
@param hostname: host name
@type hostname: str
@return: country name
@rtype: str
"""
addr = socket.gethostbyname(hostname)
return self.country_name_by_addr(addr)
def org_by_addr(self, addr):
"""
Lookup the organization (or ISP) for given IP address.
Use this method if you have an Organization/ISP database.
@param addr: IP address
@type addr: str
@return: organization or ISP name
@rtype: str
"""
try:
ipnum = ip2long(addr)
if not ipnum:
raise ValueError("Invalid IP address: %s" % addr)
if self._databaseType not in (ORG_EDITION, ISP_EDITION):
raise GeoIPError('Invalid database type; org_* methods expect '\
'Org/ISP database')
return self._get_org(ipnum)
except ValueError:
raise GeoIPError('*_by_addr methods only accept IP addresses. Use *_by_name for hostnames. (Address: %s)' % addr)
def org_by_name(self, hostname):
"""
Lookup the organization (or ISP) for hostname.
Use this method if you have an Organization/ISP database.
@param hostname: host name
@type hostname: str
@return: organization or ISP name
@rtype: str
"""
addr = socket.gethostbyname(hostname)
return self.org_by_addr(addr)
def record_by_addr(self, addr):
"""
Look up the record for a given IP address.
Use this method if you have a City database.
@param addr: IP address
@type addr: str
@return: dict with country_code, country_code3, country_name,
region, city, postal_code, latitude, longitude,
dma_code, metro_code, area_code, region_name, time_zone
@rtype: dict
"""
try:
ipnum = ip2long(addr)
if not ipnum:
raise ValueError("Invalid IP address: %s" % addr)
if not self._databaseType in (CITY_EDITION_REV0, CITY_EDITION_REV1):
raise GeoIPError('Invalid database type; record_* methods expect City database')
return self._get_record(ipnum)
except ValueError:
raise GeoIPError('*_by_addr methods only accept IP addresses. Use *_by_name for hostnames. (Address: %s)' % addr)
def record_by_name(self, hostname):
"""
Look up the record for a given hostname.
Use this method if you have a City database.
@param hostname: host name
@type hostname: str
@return: dict with country_code, country_code3, country_name,
region, city, postal_code, latitude, longitude,
dma_code, metro_code, area_code, region_name, time_zone
@rtype: dict
"""
addr = socket.gethostbyname(hostname)
return self.record_by_addr(addr)
def region_by_addr(self, addr):
"""
Lookup the region for given IP address.
Use this method if you have a Region database.
@param addr: IP address
@type addr: str
@return: dict containing country_code, region,
and region_name
@rtype: dict
"""
try:
ipnum = ip2long(addr)
if not ipnum:
raise ValueError("Invalid IP address: %s" % addr)
if not self._databaseType in (REGION_EDITION_REV0, REGION_EDITION_REV1,
CITY_EDITION_REV0, CITY_EDITION_REV1):
raise GeoIPError('Invalid database type; region_* methods expect '\
'Region or City database')
return self._get_region(ipnum)
except ValueError:
raise GeoIPError('*_by_addr methods only accept IP addresses. Use *_by_name for hostnames. (Address: %s)' % addr)
def region_by_name(self, hostname):
"""
Lookup the region for given hostname.
Use this method if you have a Region database.
@param hostname: host name
@type hostname: str
@return: dict containing country_code, region,
and region_name
@rtype: dict
"""
addr = socket.gethostbyname(hostname)
return self.region_by_addr(addr)
最佳答案
看起来 App Engine 不支持 mmap
,这并不奇怪。您可以尝试使用其他标志之一,如下所示:
import pygeoip
gi = pygeoip.GeoIP('GeoIP.dat', flags=pygeoip.const.MEMORY_CACHE)
Location = gi.country_code_by_addr(self.request.remote_addr)
如果这也不起作用,请尝试将 MEMORY_CACHE
替换为 STANDARD
。
关于python - 在 Appengine 上使用 Pygeoip - 没有名为 mmap 的模块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4608239/
我想了解 mmap 的工作原理。mmap 的用户级调用如下所示。 void *mmap(void *addr, size_t len, int prot, int flags, int
我正在做一个Bottle驱动程序,我使用 yield 关键字和 mmap.mmap 对象在输出流中发送多个映射文件,如以下代码所示: for mapping in mappings: yield
我来自 C++/RAII 世界。 所以我对何时以及如何调用 mmap.close() 感到困惑[不是 file.close()]。 或者,根本不调用它?会不会漏气? 至于来自 document 的示例
我正在我的大学上操作系统类(class),我们的任务之一是使用 mmap 实现简单的 malloc。现在我开始工作了,我尝试使用 valgrind 来检测遗留的任何错误。不管是否释放内存,valgri
有谁知道 mmap(2) 和 mmap(3) 的区别是什么?手册第 3 节被描述为“本章描述了除第 2 章中描述的实现系统调用的库函数之外的所有库函数。” mmap(3) 不执行系统调用吗? 阅读这两
我不知道我在理解mmap时错过了哪些知识。我就是想不通。但让我这样问我的问题: 我有很多(例如 3 个)文件 block ,其大小分别为 s1、s2、s3。 s1、s2 和 s3 均小于 Mmap (
在 Linux 下: #free -m total used free shared buffers cachedMem:
我正在尝试将 C 库(beaglebone PRU 驱动程序 prussdrv.c)与 Python 连接。我想要访问的特定函数返回一个 mmap 指针,如下所示: int __prussdrv_me
当我调用mmap时: ptr = mmap(NULL, ...); 并要求系统提供一个缓冲区并将文件映射到其中,然后使用 再次调用 mmap ptr2 = mmap(ptr, ...); 尝试
在 Android 上用 Java 内存映射一个大文件效果很好。但是当映射总数超过 ~1.5GB 时,即使有多个映射调用,它也会失败: mmap failed: ENOMEM (Out of memo
我在具有 64G 内存和大量磁盘空间的 debian-64 上运行一个专门的数据库守护进程。它使用磁盘上的哈希表(mmaped)并通过定期 write() 调用将实际数据写入文件。当进行大量更新时,m
C++代码: #include #include #include #include #include using namespace std; #define FILE_MODE (S_I
我想处理一个由 4Kb block 组成的文件。 随着事情的发生,我将编写更多数据并映射新部分,取消映射我不再需要的部分。 当要映射的文件数据总量约为 4Gb 时,仅 4Kb 的 map() 是否太小
大家好,我正在尝试将下面的代码转换为 python(访问树莓派 1Mhz 计时器),我不知道什么时候要映射对象,我们需要 + TIMER_OFFSET (timer = (long long int
我所做的是一个垃圾收集器,使用mmap(2)为用户空间分配空间,这就要求最初分配时可以从任何地方开始,但是后面的分配地址应该是与之前的分配连续,如下所示: page_size = getpagesiz
众所周知,最重要的 mmap() 功能是在许多进程之间共享文件映射。但众所周知,每个进程都有自己的地址空间。 问题是内存映射文件(更具体地说,它的数据)真正保存在哪里,以及进程如何访问这些内存? 我的
什么限制了内存映射文件的大小?我知道它不能大于未分配地址空间的最大连续块,并且应该有足够的可用磁盘空间。但是还有其他限制吗? 最佳答案 您太保守了:内存映射文件可能大于地址空间。 查看 内存映射文件的
如果我使用 mmap 来编写 uint32_t,我会遇到大端/小端约定的问题吗?特别是,如果我在 big-endian 机器上写入一些数据 mmap,当我尝试在 little-endian 机器上读取
所以,对于我最后一年的项目,我使用 Video4Linux2 从相机中提取 YUV420 图像,将它们解析为 x264(本地使用这些图像),然后通过 Live555 将编码流发送到 RTP/RTCP通
是 mmap在它们的效果中调用原子? 也就是说,是否由 mmap 进行了映射更改以原子方式出现在访问受影响区域的其他线程中? 作为试金石,请考虑您执行 mmap 的情况。在一个全为零的文件中(来自线程
我是一名优秀的程序员,十分优秀!