
暂无个人介绍
PHP下的cURL库主要有两个Requests和Guzzle,两个都很复杂。 Requests优先使用cURL,没有cURL时会自动启用fsockets,除非你手工指定了Transport。 Guzzle有丰富的日志库支持和日志格式,用插件订阅的方式订阅,从代码上看采用事件机制,质量更高。 它只支持cURL(至少只v3版本是),并依赖于Symfony的EventEmitter,但它被ReactPHP所依赖。 最近(2014-03-28)发现它从v3.8.1升级到v4.0.0rc,居然把Namespace改了,将前两段缩减为一段,源码目录也去掉了顶层的Guzzle,毫无意义还导致既不向前兼容,也和其他常见PHP库不一致。 现在是重点,Guzzle通常用得好好的,但昨天发现一个问题,有个远程的网址,有到支付宝去查询支付结果。调用这个网址时,Guzzle会不成功,但Requests可以。 下面是关于cURL命令的,其有两个超时时间,connect-timeout和timeout-max(后面这个通常在程序中就叫做timeout),其中后者包含前者,cURLl默认的connect-timeout是300秒,没有给timeout-max设置值,但由于包含关系,当你不设置timeout时,它至少也是300秒。 而对于PHP的fsockets,由于php.ini中有个配置项default_socket_timeout,其默认值才60秒。 另外cURL默认不支持http redirect,需要传递 -L 选项(无参数),但根据使用PHP和Python的经历,不少cURL库默认是开启了redirect,至少Guzzle的文档明确说了是开启了的,如果需要,要手动关闭。 依据: curl默认的connect-timeout是300秒 https://github.com/bagder/curl/blob/master/lib/connect.h 3.8 How do I tell curl to follow HTTP redirects? http://curl.haxx.se/docs/faq.html
问题: http://segmentfault.com/question/3032/php%E7%9A%84curl%E9%80%A0%E6%88%90%E6%80%A7%E8%83%BD%E7%93%B6%E9%A2%88-%E5%A6%82%E4%BD%95%E4%BC%98%E5%8C%96 如果是下载文件,搜索一下”php curl 多线程“ 或者看 [[http://www.lijingquan.net/php-mtidown.html|网上扒了个多线程PHP下载类]] 如果只是获得接口数据,看看 [[http://blog.longwin.com.tw/2009/10/php-multi-thread-curl-2009/|PHP 使用 CURL 同步抓取多個網頁]] 以及文章最后的参考内容 [[http://blog.csdn.net/bill200711022/article/details/6861065]] 这里提到常用方法之间的差别,还是libcurl速度和稳定性最好。另外有些框架提供了类似功能,如Fat-Free的Web::http,它也是封装了fsockopen
在MySQL v5.1和v5.5下测试部分方法不起作用。 数据表改名 ALTER TABLE `x_table` RENAME TO `y_table`; 字段改名 ALTER TABLE `x_table` RENAME `a_field` TO `b_field`; 修改字段 ALTER TABLE `x_table` CHANGE `a_field` `a_field` varchar(40) NOT NULL DEFAULT '' COMMENT '密码'; 部分修改字段 ALTER TABLE `x_table` CHANGE `a_field` SET NULL DEFAULT NULL; -- 这两个方法不正确 ALTER TABLE `x_table` CHANGE `a_field` DROP DEFAULT; 增加字段 ALTER TABLE `x_table` ADD `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID' FIRST; ALTER TABLE `x_table` ADD `b_field` varchar(40) NOT NULL DEFAULT '' COMMENT '密码' AFTER `a_field`; 删除字段 ALTER TABLE `x_table` DROP `a_field`; 修改主键自增值 ALTER TABLE `x_table` AUTO_INCREMENT=1; 或者另一个方法 OPTIMIZE TABLE `x_table`; -- 此方法无效 AUTO_INCREMENT 的值只会大于或等于 最大id + 1 当设置的AUTO_INCREMENT比上面值还小时,会自动被设置为 最大id + 1 更改主键或索引 ALTER TABLE `x_table` DROP PRIMARY KEY (`id`); ALTER TABLE `x_table` ADD KEY `m_index` (`m_field`) USING BTREE; -- Unique index
# -*- coding: utf-8 -*- from urlparse import urlsplit from httplib import HTTPConnection class HttpChecker: """ 检测网址是否存在 """ def __init__(self, domain): if "//" in domain: #网址,不止是域名 self.netloc = urlsplit(domain).netloc else: self.netloc = domain def __enter__(self): self.connection = HTTPConnection(self.netloc) return self def __exit__(self, exc_type, exc_value, traceback): del self.connection def check(self, url, splited=False): status = 0 if splited: #已经是网址中域名以后部分,必须以/开头 path = url else: netloc, path = urlsplit(url)[1:3] if netloc and netloc != self.netloc: self.netloc = netloc self.connection = HTTPConnection(self.netloc) self.connection.connect() self.connection.request("HEAD", path) status = self.connection.getresponse().status self.connection.close() return status == 200 if __name__ == "__main__": with HttpChecker("www.google.com.hk") as hc: print hc.check("http://www.google.com.hk/intl/zh-CN/options/")
一个简单的分页 # -*- coding: utf-8 -*- class PageResult(list): def __init__(self, total=0, page_no=1, page_size=0, edge_size=0): self.total = total self.page_size = page_size if page_size > 0 else 0 self.edge_size = edge_size if edge_size > 0 else 0 if page_no <= 0: self.no = 1 elif self.max >=1 and page_no > self.max: self.no = self.max else: self.no = page_no @property def start(self): return (self.no - 1) * self.page_size @property def max(self): if self.page_size > 0: return (self.total + self.page_size - 1) / self.page_size else: #不分页,显示全部条目 return 1 @property def has_prev(self): return self.no > 1 @property def has_next(self): return self.no < self.max @property def slider(self): if self.edge_size > 0: start = max(self.no - self.edge_size, 1) stop = min(self.no + self.edge_size, self.max) else: #不滑窗,显示全部页码 start, stop = 1, self.max return range(start, stop + 1) def clear(self): del self[:] def page_dict(self): page = {"curr_page":self.no, "data_count":self.total, "page_count":self.max} page["has_prev"], page["has_next"] = self.has_prev, self.has_next page["page_range"] = self.slider return page class Pagination(object): def __init__(self, query): self.query = query def all(self, offset=0, limit=0): if limit == 0: return self.query.all() else: return self.query.offset(offset).limit(limit).all() #SQLAlchemy orm return self.query.all()[offset : offset + limit] #Django orm def count(self): return self.query.count() def head(self): return self.query.first() def paginate(self, page_no=1, page_size=0, edge_size=0): result = PageResult(self.count(), page_no, page_size, edge_size) result.extend( self.all(result.start, result.page_size) ) return result
Python中的编码是个恼人的问题,第一个是文件编码,在第一行设置了#-*- coding: utf-8 -*-就可以解决。 第二个是环境编码,就是你有个中文unicode的encode或decode操作,它给你报错。 我们最不喜欢看见这段出错信息了: UnicodeDecodeError: 'ascii' codec can't decode byte 0xe6 in position 0: ordinal not in range(128) 加入这段代码在项目入口文件开头,可以解决这个问题。 import sys try: reload(sys) sys.setdefaultencoding("utf-8") except AttributeError: pass #没起作用 或者将这段代码放在项目根目录下的sitecustomize.py文件中。 问题是python2.5之后的版本,有时不在项目开头自动加载这个文件。纠结啊,自己定义的方式自己有时不支持。 只好在入口文件加一段,确保执行sitecustomize.py # -*- coding: utf-8 -*- #解决Python2.5之后有时无法载入sitecustomize.py的问题 import sys import os sys.path = [os.getcwd()] + sys.path import sitecustomize reload(sitecustomize) 另外关于python的搜索路径PYTHONPATH,可以用以下方式增加一个路径到其中,比如项目根目录下的library # -*- coding: utf-8 -*- import os.path import sys import site try: reload(sys) sys.setdefaultencoding("utf-8") except AttributeError: pass base_dir = os.path.dirname(os.path.abspath(__file__)) prev_sys_path = list(sys.path) # site.addsitedir adds this directory to sys.path then scans for .pth files # and adds them to the path too. site.addsitedir(os.path.join(base_dir, 'library')) # addsitedir adds its directories at the end, but we want our local stuff # to take precedence over system-installed packages. # See http://code.google.com/p/modwsgi/issues/detail?id=112 new_sys_path = [] for item in list(sys.path): if item not in prev_sys_path: new_sys_path.append(item) sys.path.remove(item) sys.path[:0] = new_sys_path
用gevent(或封装了gevent的gunicore)启动python进程,会出现多个独立进程同时写一个日志文件, 可以观察到有日志部分丢失:一个进程日志没写完,另一个进程把日志覆盖在同一行的后面;有些日志甚至完全丢失。 用mlogging包可以解决多进程写日志的问题,没有发现不完整的日志,是否丢失日志有待进一步检测。 下面是一个在python程序中记录重要信息,以便以后解析统计的函数 # -*- coding: utf-8 -*- import os.path import logging from mlogging import FileHandler_MP, TimedRotatingFileHandler_MP from functools import partial class LevelFilter(logging.Filter): def __init__(self, level, *args, **kwargs): #super(LevelFilter, self).__init__(*args, **kwargs) self.level = level def filter(self, record): return record.levelno == self.level def init_info_logger(name, logging_dir): logging_file = os.path.join(logging_dir, name+".log") handler = TimedRotatingFileHandler_MP(logging_file, "midnight", 1) handler.setFormatter( logging.Formatter( "%(asctime)s %(levelname)-8s %(name)-20s %(message)s", #设置日志格式,固定宽度便于解析 datefmt = "%Y-%m-%d %H:%M:%S" #设置asctime时间格式 )) handler.suffix = "%Y%m%d" #只记录INFO级别信息,抛弃上面的WARNING、ERROR、CRITICAL几个级别 handler.addFilter( LevelFilter(logging.INFO) ) logger = logging.getLogger(name) logger.setLevel(logging.INFO) #有些Python版本会报错KeyError,找不到clientip或user,这里用一个短横(-)做默认值 extra={"clientip":"-", "user":"-"} #exc_info是出错时的Debug详细回溯信息,这里禁止记录,只记录错误信息这一行 setattr(logger, "info", partial(logger.info, exc_info=False, extra=extra)) logger.addHandler( handler ) return logger def init_error_logger(logging_dir): logging_file = os.path.join(logging_dir, "errors.log") handler = FileHandler_MP(logging_file) handler.setFormatter( logging.Formatter( "%(asctime)s %(levelname)-8s %(message)s", #设置日志格式,固定宽度便于解析 datefmt = "%Y-%m-%d %H:%M:%S" #设置asctime时间格式 )) logger = logging.getLogger() logger.setLevel(logging.WARNING) #有些Python版本会报错KeyError,找不到clientip或user,这里用一个短横(-)做默认值 extra={"clientip":"-", "user":"-"} #exc_info是出错时的Debug详细回溯信息 setattr(logger, "critical", partial(logger.critical, exc_info=True, extra=extra)) setattr(logger, "error", partial(logger.error, exc_info=True, extra=extra)) setattr(logger, "warning", partial(logger.warning, exc_info=True, extra=extra)) logger.addHandler( handler ) return logger if __name__ == "__main__": logger = init_info_logger("test", "./") logger.debug("低级别的DEBUG,不会记录。") logger.info("哈哈哈,这才是我想要的信息,请记下来。") logger.error("高级别的ERROR,也被过滤掉。")
# -*- coding: utf-8 -*- import hashlib def md5hex(word): """ MD5加密算法,返回32位小写16进制符号 """ if isinstance(word, unicode): word = word.encode("utf-8") elif not isinstance(word, str): word = str(word) m = hashlib.md5() m.update(word) return m.hexdigest() def md5sum(fname): """ 计算文件的MD5值 """ def read_chunks(fh): fh.seek(0) chunk = fh.read(8096) while chunk: yield chunk chunk = fh.read(8096) else: #最后要将游标放回文件开头 fh.seek(0) m = hashlib.md5() if isinstance(fname, basestring) \ and os.path.exists(fname): with open(fname, "rb") as fh: for chunk in read_chunks(fh): m.update(chunk) #上传的文件缓存 或 已打开的文件流 elif fname.__class__.__name__ in ["StringIO", "StringO"] \ or isinstance(fname, file): for chunk in read_chunks(fname): m.update(chunk) else: return "" return m.hexdigest()
首先安装 Flask-SqlAlchem? v0.15 和 SqlAutoCode? v0.7 在配置文件settings中设置 SQLALCHEMY_DATABASE_URI = 'mysql://kw3:123456@localhost/kw3_article' SQLALCHEMY_BINDS = { 'game': 'mysql://kw3:123456@localhost/kw_game', } TABLE_PREFIX = 't_' 将最后面的代码放到scripts下,并运行它。 如存为generate_models.py文件,python scripts/generate_models.py 在项目入口文件中 #-*- coding: utf-8 -*- from flask import Flask from models.base.db import db app = Flask(__name__) db.init_app(app) 你就可以在view中使用了,具体参考 http://packages.python.org/Flask-SQLAlchemy/index.html 自动产生models的脚本: #-*- coding: utf-8 -*- #使用SqlAutocode,根据数据库已有表,产生符合Flask-SqlAlchemy要求的models的定义 import os.path from flask import Flask from sqlautocode import config from sqlautocode.declarative import * from sqlautocode.formatter import _repr_coltype_as from flask.ext.sqlalchemy import SQLAlchemy singular = plural = lambda x: x constants.COLUMN = 'db.' + constants.COLUMN constants.HEADER_DECL = """from sqlalchemy import * if __name__ == '__main__': from flask import Flask from flask.ext.sqlalchemy import SQLAlchemy app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = '%s' db = SQLAlchemy(app) else: from .db import db """ def no_prefix_wrapper(f, prefix=None): def _name2label(name, schema=None): if schema: if name.startswith(schema+'.'): name = '.'.join(name.split('.')[1:]) if prefix and name.startswith(prefix): name = name[ len(prefix):] label = str(''.join([s.capitalize() for s in re.findall(r'([A-Z][a-z0-9]+|[a-z0-9]+|[A-Z0-9]+)', name)])) return label return _name2label def column_repr(self): kwarg = [] if self.key != self.name: kwarg.append( 'key') if hasattr(self, 'primary_key') and self.primary_key: self.primary_key = True kwarg.append( 'primary_key') if not self.nullable: kwarg.append( 'nullable') if self.onupdate: kwarg.append( 'onupdate') if self.default: kwarg.append( 'default') ks = ', '.join('%s=%r' % (k, getattr(self, k)) for k in kwarg) if self.server_default: ks += ', ' if ks else '' ks += ('default=%s' % self.server_default.arg.text) name = self.name if not hasattr(config, 'options') and self.config.options.generictypes: coltype = repr(self.type) elif type(self.type).__module__ == 'sqlalchemy.types': coltype = repr(self.type) else: # Try to 'cast' this column type to a cross-platform type # from sqlalchemy.types, dropping any database-specific type # arguments. for base in type(self.type).__mro__: if (base.__module__ == 'sqlalchemy.types' and base.__name__ in sqlalchemy.__all__): coltype = _repr_coltype_as(self.type, base) break # FIXME: if a dialect has a non-standard type that does not # derive from an ANSI type, there's no choice but to ignore # generic-types and output the exact type. However, import # headers have already been output and lack the required # dialect import. else: coltype = repr(self.type) data = {'name': self.name, 'type': coltype, 'constraints': ', '.join(["ForeignKey('%s')"%cn.target_fullname for cn in self.foreign_keys]), 'args': ks and ks or '', } if data['constraints']: if data['constraints']: data['constraints'] = ', ' + data['constraints'] if data['args']: if data['args']: data['args'] = ', ' + data['args'] return constants.COLUMN % data class FlaskModelFactory(ModelFactory): def __init__(self, name, conn): self.name = name argv = ['sqlautocode', conn, '-d', '-g', '-i'] config.configure(argv) config.interactive, config.schema, config.example = None, None, False super(FlaskModelFactory, self).__init__(config) def _table_repr(self, table): s = "db.Table(u'%s',\n"%(table.name) for column in table.c: s += " %s,\n"%column_repr(column) if self.name != "default": s +=" info={'bind_key': '%s'}\n"%self.name #if table.schema: # s +=" schema='%s'\n"%table.schema s+=")" return s def create_model(self, table): #partially borrowed from Jorge Vargas' code #http://dpaste.org/V6YS/ log.debug('Creating Model from table: %s'%table.name) model_name = self.find_new_name(singular(name2label(table.name)), self.used_model_names) self.used_model_names.append(model_name) is_many_to_many_table = self.is_many_to_many_table(table) table_name = self.find_new_name(table.name, self.used_table_names) self.used_table_names.append(table_name) mtl = self.model_table_lookup class Temporal(self.DeclarativeBase): __table__ = table @classmethod def _relation_repr(cls, rel): target = rel.argument if target and inspect.isfunction(target): target = target() if isinstance(target, Mapper): target = target.class_ target = target.__name__ primaryjoin='' lookup = mtl() if rel.primaryjoin is not None and hasattr(rel.primaryjoin, 'right'): right_lookup = lookup.get(rel.primaryjoin.right.table.name, '%s.c'%rel.primaryjoin.right.table.name) left_lookup = lookup.get(rel.primaryjoin.left.table.name, '%s.c'%rel.primaryjoin.left.table.name) primaryjoin = ", primaryjoin='%s.%s==%s.%s'"%(left_lookup, rel.primaryjoin.left.name, right_lookup, rel.primaryjoin.right.name) elif hasattr(rel, '_as_string'): primaryjoin=', primaryjoin="%s"'%rel._as_string secondary = '' secondaryjoin = '' if rel.secondary is not None: secondary = ", secondary=%s"%rel.secondary.name right_lookup = lookup.get(rel.secondaryjoin.right.table.name, '%s.c'%rel.secondaryjoin.right.table.name) left_lookup = lookup.get(rel.secondaryjoin.left.table.name, '%s.c'%rel.secondaryjoin.left.table.name) secondaryjoin = ", secondaryjoin='%s.%s==%s.%s'"%(left_lookup, rel.secondaryjoin.left.name, right_lookup, rel.secondaryjoin.right.name) backref='' # if rel.backref: # backref=", backref='%s'"%rel.backref.key return "%s = relation('%s'%s%s%s%s)"%(rel.key, target, primaryjoin, secondary, secondaryjoin, backref) @classmethod def __repr__(cls): try: mapper = None try: mapper = class_mapper(cls) except exc.InvalidRequestError: log.warn("A proper mapper could not be generated for the class %s, no relations will be created"%model_name) s = "" s += "class "+model_name+'(db.Model):\n' if cls.__bind_key__ != "default": s += " __bind_key__ = '%s'\n"%cls.__bind_key__ if is_many_to_many_table: s += " __table__ = %s\n\n"%table_name else: s += " __tablename__ = '%s'\n"%table_name if hasattr(cls, '__table_args__'): #if cls.__table_args__[0]: #for fkc in cls.__table_args__[0]: # fkc.__class__.__repr__ = foreignkeyconstraint_repr # break s+=" __table_args__ = %s\n"%cls.__table_args__ s+="\n" for column in cls.__table__.c: s += " %s = %s\n"%(column.name, column_repr(column)) ess = s # this is only required in SA 0.5 if mapper and RelationProperty: for prop in mapper.iterate_properties: if isinstance(prop, RelationshipProperty): s+=' %s\n'%cls._relation_repr(prop) return s except Exception, e: log.error("Could not generate class for: %s"%cls.__name__) from traceback import format_exc log.error(format_exc()) return '' #hack the class to have the right classname Temporal.__name__ = model_name #set up some blank table args Temporal.__table_args__ = {} #add in the schema Temporal.__bind_key__ = self.name #if self.config.schema: # Temporal.__table_args__[1]['schema'] = table.schema #trick sa's model registry to think the model is the correct name if model_name != 'Temporal': Temporal._decl_class_registry[model_name] = Temporal._decl_class_registry['Temporal'] del Temporal._decl_class_registry['Temporal'] #add in single relations fks = self.get_single_foreign_keys_by_column(table) for column, fk in fks.iteritems(): related_table = fk.column.table if related_table not in self.tables: continue log.info(' Adding <primary> foreign key for:%s'%related_table.name) backref_name = plural(table_name) rel = relation(singular(name2label(related_table.name, related_table.schema)), primaryjoin=column==fk.column)#, backref=backref_name) setattr(Temporal, related_table.name, _deferred_relationship(Temporal, rel)) #add in the relations for the composites for constraint in table.constraints: if isinstance(constraint, ForeignKeyConstraint): if len(constraint.elements) >1: related_table = constraint.elements[0].column.table related_classname = singular(name2label(related_table.name, related_table.schema)) primary_join = "and_(%s)"%', '.join(["%s.%s==%s.%s"%(model_name, k.parent.name, related_classname, k.column.name) for k in constraint.elements]) rel = relation(related_classname, primaryjoin=primary_join #foreign_keys=[k.parent for k in constraint.elements] ) rel._as_string = primary_join setattr(Temporal, related_table.name, rel) # _deferred_relationship(Temporal, rel)) #add in many-to-many relations for join_table in self.get_related_many_to_many_tables(table.name): if join_table not in self.tables: continue primary_column = [c for c in join_table.columns if c.foreign_keys and list(c.foreign_keys)[0].column.table==table][0] for column in join_table.columns: if column.foreign_keys: key = list(column.foreign_keys)[0] if key.column.table is not table: related_column = related_table = list(column.foreign_keys)[0].column related_table = related_column.table if related_table not in self.tables: continue log.info(' Adding <secondary> foreign key(%s) for:%s'%(key, related_table.name)) setattr(Temporal, plural(related_table.name), _deferred_relationship(Temporal, relation(singular(name2label(related_table.name, related_table.schema)), secondary=join_table, primaryjoin=list(primary_column.foreign_keys)[0].column==primary_column, secondaryjoin=column==related_column ))) break; return Temporal def gen_models_dir(app, models_dir): #找到并建立models文件夹和__init__.py文件 if not models_dir: app_root = app.config.get('APPLICATION_ROOT', '') if not app_root: app_root = os.path.dirname( os.path.dirname( os.path.realpath(__file__) ) ) models_dir = os.path.join(app_root, 'models') if not os.path.exists(models_dir): os.mkdir(models_dir) init_file = os.path.join(models_dir, '__init__.py') with open(init_file, 'wb') as fh: fh.write('#-*- coding: utf-8 -*-\n') return models_dir def write_db_file(db_file): #建立数据库定义文件 with open(db_file, 'wb') as fh: fh.write('#-*- coding: utf-8 -*-\n') fh.write('\n') fh.write('from flask.ext.sqlalchemy import SQLAlchemy\n') fh.write('\n\n') fh.write('db = SQLAlchemy()\n') def write_schema_file(factory, schema_file, name='default'): #建立数据库定义文件 with open(schema_file, 'wb') as fh: fh.write("#-*- coding: utf-8 -*-\n") fh.write('\n') fh.write( repr(factory) ) fh.write('\n') fh.write("if __name__ == '__main__':\n") if name == 'default': fh.write(" db.create_all(bind=None)\n") else: fh.write(" db.create_all(bind=['%s'])\n" % name) def generate_models(app, models_dir=None): db = SQLAlchemy(app) conns = { 'default': app.config.get('SQLALCHEMY_DATABASE_URI') or {}, } conns.update( app.config.get('SQLALCHEMY_BINDS') or {} ) models_dir = gen_models_dir(app, models_dir) db_file = os.path.join(models_dir, 'db.py') if not os.path.exists(db_file): write_db_file(db_file) for name, conn in conns.items(): if not conn: continue schema_file = os.path.join(models_dir, '%s.py' % name) if not os.path.exists(schema_file): factory = FlaskModelFactory(name, conn) write_schema_file(factory, schema_file, name) if __name__ == '__main__': import sys sys.path.append( os.path.dirname( os.path.dirname( os.path.realpath(__file__) ) ) ) app = Flask(__name__) app.config.from_object('settings') name2label = no_prefix_wrapper(name2label, app.config.get('TABLE_PREFIX')) generate_models(app)
前几年自己用过一段时间的git(原来是使用bzr,后来换成git),都是当作个人代码备份工具,没有涉及多人提交代码到中央版本库。 两个月前,我们把原来的svn版本管理换成了git,这两天提交版本时遇到许多问题,上网找些资料看,才发现用法不对,集体使用时,不能简单地再延续原来个人使用时的习惯。 背景啰嗦完了,现在进入正题:如何提交避免版本冲突。 首先在本地按方法1 clone 回来之后,只有一个默认分支master,不要直接在上面工作。 建立一个自己的分支,如取名working: git branch working 切换到这个新分支: git checkout working 现在可以自由修改代码并保存了。 确保你修改的代码都是自己负责项目下,或者说你的两次提交之间,没有其他人来改相同项目下的代码, 如果不能避免,你就要在下面的merge步骤手工处理冲突了。 提交代码时按下面的步骤: 可以将下面的脚本保存在你的每个项目之下,每次只修改提交一个项目。 git checkout working --force #确保使用的是工作分支 git add . git commit -m"$1" -a #提交代码到本地,工作分支增加一个版本,这里的$1是运行脚本的第一个参数 git checkout master git pull origin master #切换回默认分支,并将默认分支和中央最新版本合并 git merge working #在本地合并你的这次修改到默认分支 git push origin master #提交到中央版本库,接下来还是要切换回工作分支的 git checkout working --force 如果不小心动了生产环境(就是只从中央版本库pull到本地)的文件,只好将本地版本退回一个,再从中央代码库pull代码合并。 git reset --hard HEAD
How to change svn server name without making a new cosvn server You must specify the old and new like this: svn sw --relocate svn://example1.com:22/name http://example2.com:24/edc From http://how-to.wikia.com/wiki/How_to_change_svn_server_name_without_making_a_new_co
#-*- coding: utf-8 -*- from bisect import bisect FIRST_LETTERS = ["a", "b", "c", "d", "e", "f", "g", "h", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "w", "x", "y", "z"] FIRST_NUMBERS = [1, 37, 233, 478, 674, 702, 833, 994, 1187, 1506, 1612, 1872, 2035, 2122, 2130, 2258, 2427, 2486, 2790, 2958, 3084, 3325, 3649] PINYIN_LETTERS = [ ['a', 'ai', 'an', 'ang', 'ao'], ['ba', 'bai', 'ban', 'bang', 'bao', 'bei', 'ben', 'beng', 'bi', 'bian', 'biao', 'bie', 'bin', 'bing', 'bo', 'bu'], ['ca', 'cai', 'can', 'cang', 'cao', 'ce', 'ceng', 'cha', 'chai', 'chan', 'chang', 'chao', 'che', 'chen', 'cheng', 'chi', 'chong', 'chou', 'chu', 'chuan', 'chuang', 'chui', 'chun', 'chuo', 'ci', 'cong', 'cou', 'cu', 'cuan', 'cui', 'cun', 'cuo'], ['da', 'dai', 'dan', 'dang', 'dao', 'de', 'deng', 'di', 'dian', 'diao', 'die', 'ding', 'diu', 'dong', 'dou', 'du', 'duan', 'dui', 'dun', 'duo'], ['e', 'en', 'er'], ['fa', 'fan', 'fang', 'fei', 'fen', 'feng', 'fo', 'fou', 'fu'], ['ga', 'gai', 'gan', 'gang', 'gao', 'ge', 'gei', 'gen', 'geng', 'gong', 'gou', 'gu', 'gua', 'guai', 'guan', 'guang', 'gui', 'gun', 'guo'], ['ha', 'hai', 'han', 'hang', 'hao', 'he', 'hei', 'hen', 'heng', 'hong', 'hou', 'hu', 'hua', 'huai', 'huan', 'huang', 'hui', 'hun', 'huo'], ['ji', 'jia', 'jian', 'jiang', 'jiao', 'jie', 'jin', 'jing', 'jiong', 'jiu', 'ju', 'juan', 'jue', 'jun'], ['ka', 'kai', 'kan', 'kang', 'kao', 'ke', 'ken', 'keng', 'kong', 'kou', 'ku', 'kua', 'kuai', 'kuan', 'kuang', 'kui', 'kun', 'kuo'], ['la', 'lai', 'lan', 'lang', 'lao', 'le', 'lei', 'leng', 'li', 'lia', 'lian', 'liang', 'liao', 'lie', 'lin', 'ling', 'liu', 'long', 'lou', 'lu', 'lv', 'lue', 'lv', 'lu', 'luan', 'lue', 'lun', 'luo'], ['ma', 'mai', 'man', 'mang', 'mao', 'me', 'mei', 'men', 'meng', 'mi', 'mian', 'miao', 'mie', 'min', 'ming', 'miu', 'mo', 'mou', 'mu'], ['na', 'nai', 'nan', 'nang', 'nao', 'ne', 'nei', 'nen', 'neng', 'ni', 'nian', 'niang', 'niao', 'nie', 'nin', 'ning', 'niu', 'nong', 'nu', 'nv', 'nuan', 'nue', 'nuo'], ['o', 'ou'], ['pa', 'pai', 'pan', 'pang', 'pao', 'pei', 'pen', 'peng', 'pi', 'pian', 'piao', 'pie', 'pin', 'ping', 'po', 'pou', 'pu'], ['qi', 'qia', 'qian', 'qiang', 'qiao', 'qie', 'qin', 'qing', 'qiong', 'qiu', 'qu', 'quan', 'que', 'qun'], ['ran', 'rang', 'rao', 're', 'ren', 'reng', 'ri', 'rong', 'rou', 'ru', 'ruan', 'rui', 'run', 'ruo'], ['sa', 'sai', 'san', 'sang', 'sao', 'se', 'sen', 'seng', 'sha', 'shai', 'shan', 'shang', 'shao', 'she', 'shen', 'sheng', 'shi', 'shou', 'shu', 'shua', 'shuai', 'shuan', 'shuang', 'shui', 'shun', 'shuo', 'si', 'song', 'sou', 'su', 'suan', 'sui', 'sun', 'suo'], ['ta', 'tai', 'tan', 'tang', 'tao', 'te', 'teng', 'ti', 'tian', 'tiao', 'tie', 'ting', 'tong', 'tou', 'tu', 'tuan', 'tui', 'tun', 'tuo'], ['wa', 'wai', 'wan', 'wang', 'wei', 'wen', 'weng', 'wo', 'wu'], ['xi', 'xia', 'xian', 'xiang', 'xiao', 'xie', 'xin', 'xing', 'xiong', 'xiu', 'xu', 'xuan', 'xue', 'xun'], ['ya', 'yan', 'yang', 'yao', 'ye', 'yi', 'yin', 'ying', 'yo', 'yong', 'you', 'yu', 'yuan', 'yue', 'yun'], ['za', 'zai', 'zan', 'zang', 'zao', 'ze', 'zeng', 'zha', 'zhai', 'zhan', 'zhang', 'zhao', 'zhe', 'zhen', 'zheng', 'zhi', 'zhong', 'zhou', 'zhu', 'zhua', 'zhuai', 'zhuan', 'zhuang', 'zhui', 'zhun', 'zhuo', 'zi', 'zong', 'zou', 'zu', 'zuan', 'zui', 'zun', 'zuo'] ] PINYIN_NUMBERS = [ [2, 3, 16, 25, 28], [37, 55, 63, 78, 90, 113, 128, 132, 138, 162, 174, 178, 182, 188, 203, 222], [233, 234, 245, 252, 257, 262, 267, 269, 280, 283, 293, 312, 321, 327, 337, 352, 368, 373, 385, 408, 415, 421, 426, 433, 435, 447, 453, 454, 458, 461, 469, 472], [478, 484, 502, 517, 522, 534, 537, 544, 563, 579, 588, 601, 610, 611, 621, 629, 643, 649, 653, 662], [674, 687, 688], [702, 710, 727, 738, 750, 765, 780, 781, 782], [833, 835, 841, 852, 861, 871, 888, 889, 891, 904, 919, 928, 946, 952, 955, 966, 969, 985, 988], [994, 1001, 1008, 1027, 1030, 1039, 1057, 1059, 1063, 1068, 1077, 1084, 1108, 1117, 1122, 1136, 1150, 1171, 1177], [1187, 1246, 1263, 1309, 1322, 1350, 1377, 1403, 1428, 1430, 1447, 1472, 1479, 1489], [1506, 1510, 1515, 1521, 1528, 1532, 1547, 1551, 1553, 1557, 1561, 1568, 1573, 1577, 1579, 1587, 1604, 1608], [1612, 1619, 1622, 1637, 1644, 1653, 1655, 1666, 1669, 1709, 1710, 1724, 1735, 1748, 1753, 1765, 1779, 1790, 1805, 1811, 1831, 1842, 1843, 1844, 1845, 1851, 1853, 1860], [1872, 1881, 1887, 1902, 1908, 1920, 1921, 1937, 1940, 1948, 1962, 1971, 1979, 1981, 1987, 1993, 1994, 2017, 2020], [2035, 2042, 2047, 2050, 2051, 2056, 2057, 2059, 2060, 2061, 2072, 2080, 2081, 2083, 2090, 2091, 2103, 2107, 2111, 2114, 2115, 2116, 2119], [2122, 2123], [2130, 2136, 2142, 2150, 2155, 2162, 2171, 2173, 2187, 2210, 2214, 2218, 2220, 2225, 2234, 2243, 2244], [2258, 2294, 2303, 2325, 2333, 2348, 2353, 2364, 2377, 2379, 2387, 2407, 2417, 2425], [2427, 2431, 2436, 2439, 2441, 2451, 2453, 2454, 2464, 2467, 2477, 2479, 2482, 2484], [2486, 2489, 2493, 2503, 2506, 2510, 2513, 2514, 2515, 2524, 2526, 2542, 2550, 2561, 2573, 2589, 2606, 2653, 2663, 2702, 2704, 2708, 2710, 2713, 2717, 2721, 2725, 2741, 2749, 2753, 2765, 2768, 2779, 2782], [2790, 2805, 2814, 2832, 2845, 2856, 2857, 2861, 2876, 2884, 2889, 2892, 2908, 2921, 2925, 2936, 2938, 2944, 2947], [2958, 2965, 2967, 2984, 2994, 3033, 3043, 3046, 3055], [3084, 3125, 3138, 3164, 3184, 3208, 3229, 3239, 3254, 3261, 3270, 3289, 3305, 3311], [3325, 3341, 3374, 3391, 3412, 3427, 3480, 3502, 3520, 3521, 3536, 3556, 3607, 3627, 3637], [3649, 3652, 3659, 3663, 3666, 3680, 3686, 3690, 3710, 3716, 3733, 3748, 3758, 3768, 3784, 3805, 3848, 3859, 3873, 3905, 3907, 3908, 3914, 3921, 3927, 3929, 3940, 3955, 3962, 3966, 3974, 3976, 3980, 3982] ] def gb2312_pinyin(unichar, first_letter=False): assert(isinstance(unichar, unicode)) gbkchar = unichar.encode("GBK") high_code = ord(gbkchar[0]) - 160 #GBK区码 low_code = ord(gbkchar[1]) - 160 #GBK位码 char_code = (high_code - 16) * 100 + low_code if -1299 <= char_code <= -1206: return chr(char_code + 1332) #全角转半角 elif char_code < 1 or char_code > 3989: return "" #不是汉字,或者未被GB2312收录的生僻字 idx = bisect(FIRST_NUMBERS, char_code) if first_letter: #找首字母 result = FIRST_LETTERS[idx - 1] else: #完整拼音 inidx = bisect(PINYIN_NUMBERS[idx - 1], char_code) result = PINYIN_LETTERS[idx - 1][inidx - 1] return result def to_unicode(word): if not isinstance(word, unicode): try: #尝试当作UTF-8编码转为UNICODE word = unicode(word, "UTF-8") except UnicodeDecodeError: try: #尝试当作GBK编码转为UNICODE word = unicode(word, "GBK") except UnicodeDecodeError: word = "" return word def split_sentence(sentence): """ 将中英文混合的句子分割成单个汉字和连续英文 """ word = "" for character in sentence: if ord(character) <= 255: #ASCII word += character else: yield True, word word = "" yield False, character yield True, word def words_to_pinyin(words, first_letter=False, seperator=""): uniwords = to_unicode(words) letters = [] for is_ascii, word in split_sentence(uniwords): if word: if not is_ascii: word = gb2312_pinyin(word, first_letter) letters.append(word) return seperator.join(letters) def words_pinyin_for_sort(words, first_letter=False): uniwords = to_unicode(words) word_pinyin = words_to_pinyin(uniwords, first_letter, seperator="~") if len(uniwords) > 0 and ord(uniwords[0]) > 255: word_pinyin = "~" + word_pinyin return word_pinyin if "__main__"==__name__: print words_to_pinyin("好V5的中文", first_letter=True) print words_to_pinyin("好V5的中文!", seperator=" ") print words_pinyin_for_sort("好V5的中文!")
把代码放到局域网服务器,原本在本地运行正常的代码在局域网服务器上却报错,Google一下相关错误,原来是Python2.6的一个Bug。 Python2.6下,如果有dict的key是unicode,当把它解包传给函数作为参数时,会报错 from datetime import * date(1,2,**{u'day':10,u'x':20}) TypeError: date() keywords must be strings 在Python2.7下不会有问题。 参看 http://bugs.python.org/issue2646
先要安装maillib库 假设我要获得一周来,豆瓣发送的每个邮件中的第一个网址 import poplib import maillib from datetime import datetime, timedelta def email_filter(sender, body): target = "http://" sender, body = sender[1], body.split("\n") if sender == "webmaster@douban.com": for line in body: if target in line: return line.strip() def read_email(email, password, host, port=110, days=0): conn = poplib.POP3(host, port) #conn.set_debuglevel(1) #输出调试信息 conn.user(email) conn.pass_(password) links = [] nr = conn.stat()[0] #获取邮件数量 for i in range(nr, 0, -1): server_msg, body, octets = conn.retr(i) msg = maillib.Message.from_string( "\n".join(body) ) today = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0) if msg.date < today - timedelta(days=days): break link = email_filter(msg.sender, msg.body) if link: links.append(link) return links if __name__ == "__main__": links = read_email("me@126.com", "pass", host="pop.126.com", days=7) for link in links: print link
reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v "path" /d "%path%;%cd%" /t REG_SZ /f 如果当前路径已经存在于系统路径,不会重复添加。 附件是Unix下的常用命令的windows版本,并含有最新的gawk 4.0,与windows冲突的date、mkdir、rmdir、echo、ln、install等命令,文件名前面多加了一个g。
如果你的awk代码可以在Linux可以跑,在Windows下却不行,请检查代码中是否有百分号%,将所有%转义为%%。 例如我的这段处理Nginx日志时间的代码: date = substr($2,2,11) time = substr($2,14,8) gsub("/"," ",date) command = "gdate -d \"" date " " time "\" +%%s" command | getline datetime
def unique_list(seq, excludes=[]): """ 返回包含原列表中所有元素的新列表,将重复元素去掉,并保持元素原有次序 excludes: 不希望出现在新列表中的元素们 """ seen = set(excludes) # seen是曾经出现的元素集合 return [x for x in seq if x not in seen and not seen.add(x)] 参考: http://www.peterbe.com/plog/uniqifiers-benchmark
用Jquery 1.4.4 实现的联动下拉菜单,估计在Jquery 1.2版本以上都可用。 联动下拉菜单是一主一从两个select,切换主select时,从select的内容跟着改变。这里是把从select的项目按组optgroup全部加载进来,然后切换主select时更新从select组的显示或者隐藏。注意从select的组次序和主select项次序要一致。 HTML代码 <select id="province"> <option value="GD">广东</option> <option value="JS">江苏</option> <option value="FJ">福建</option> </select> <select id="city"> <option value="">(全部)</option> <optgroup label="广东"> <option value="020">广州</option> <option value="0755">深圳</option> </optgroup> <optgroup label="江苏"> <option value="025">南京</option> <option value="0512">苏州</option> </optgroup> <optgroup label="福建"> <option value="0591">福州</option> <option value="0592">厦门</option> </optgroup> </select> JS代码 function double_select(master, slave){ var change_slave = function() { var idx = $(master).attr("selectedIndex") + 1; $(slave).children("optgroup").hide(); $(slave).children("optgroup:nth-child("+idx+")").show(); } $(master).change( change_slave ); change_slave(); } //使用 $(function(){ double_select("#province", "#city"); });
import urllib import urlparse def url_add_params(url, **params): """ 在网址中加入新参数 """ pr = urlparse.urlparse(url) query = dict(urlparse.parse_qsl(pr.query)) query.update(params) prlist = list(pr) prlist[4] = urllib.urlencode(query) return urlparse.ParseResult(*prlist).geturl() if __name__ == "__main__": url = 'http://bbs.163.com/viewthread.php?tid=1660&rpid=5798&ordertype=0&page=1#pid5798' print url_add_params(url, token=123, site="bbs")
用途当然是模拟浏览器 # -*- coding: utf-8 -*- """ 使用pycurl发起HTTP访问 """ import pycurl, urllib import StringIO def curl(url, method="GET", proxy=(), verbose=0, cookie_file="", **kwargs): #proxy = ("www.test.com:8080", "SOCKS5", "user:pass") req = pycurl.Curl() req.setopt(pycurl.FOLLOWLOCATION, 1) req.setopt(pycurl.MAXREDIRS, 5) req.setopt(pycurl.CONNECTTIMEOUT, 60) req.setopt(pycurl.TIMEOUT, 600) req.setopt(pycurl.HTTPPROXYTUNNEL, 1) req.setopt(pycurl.VERBOSE, verbose) agent = kwargs.pop("agent", "Mozilla/4.0") req.setopt(pycurl.USERAGENT, agent) if cookie_file: req.setopt(pycurl.COOKIEJAR, cookie_file) req.fp = StringIO.StringIO() req.setopt(pycurl.WRITEFUNCTION, req.fp.write) data = urllib.urlencode(kwargs) if method.upper() == "GET": if data: url = url + "?" + data req.setopt(pycurl.URL, url) else: req.setopt(pycurl.URL, url) req.setopt(pycurl.POSTFIELDS, data) if proxy: host_port, sock_type, user_pass = proxy req.setopt(pycurl.PROXY, host_port) req.setopt(pycurl.PROXYTYPE, sock_type) req.setopt(pycurl.PROXYUSERPWD, user_pass) req.perform() return req.fp.getvalue()
添加一个用户dba,密码sql,可以管理db_开头的数据库 GRANT ALL PRIVILEGES ON `db\_`.* TO 'dba'@'localhost' IDENTIFIED BY 'sql' WITH GRANT OPTION; FLUSH PRIVILEGES; 从其他机器访问 如果要允许从其他机器访问,要修改 etc/mysql/my.cnf 将 bind-address = 127.0.0.1 注释掉,或者修改为 bind-address = 0.0.0.0 (bind-address只能绑定单个IP或者所有IP,无法指定网段或IP列表) 修改用户密码 SET PASSWORD FOR 'ryan'@'localhost'=PASSWORD('newpass');
昨天装好了Couchdb-1.0.2,用couchdb -b启动正常,用curl http://127.0.0.1:5984/也能收到欢迎信息,却打不开网页客户端Futon。 想起之前也碰到这样的问题,第二天自己好了,就把Linux重启了一下,解决了!应该是某个依赖的进程需要重启,猜测是js spidemokey。 第二个问题又来了,很小的一个数据库,半天生成不了一个View,而且CPU马上飙到最高。开始以为是erlang没装好,因为要使用beam.smp嘛,就把erlang和couchdb先后重装一次,问题没解决。 后来用关键词couchdb view no response搜索了一下,找到了这个 CouchDB 0.11 - no views/useless CPU usage 原来是ld.so.conf中的xulrunner库的位置不正确(版本和couchdb使用的不一致) 对于每次用couchdb -b启动时,都会在当前目录留下两个日志文件的问题,我的解决方法很简单粗暴:couchdb实际上是个python文件,找到它(couchdb目录的bin/下面),强制指定输出目录 STDERR_FILE=/opt/couchdb-1.0.2/var/log/couchdb/couchdb.stderr STDOUT_FILE=/opt/couchdb-1.0.2/var/log/couchdb/couchdb.stdout
转自 http://my.oschina.net/captaintheron/blog/8898 下面,本文就将结合具体的例子来说明怎样利用curl进行下载。 1、获得一张页面 使用命令:curl http://curl.haxx.se 这是最简单的使用方法。用这个命令获得了http://curl.haxx.se指向的页面,同样,如果这里的URL指向的是一个文件或者一幅图都可以直接下载到本地。如果下载的是HTML文档,那么缺省的将不显示文件头部,即HTML文档的header。要全部显示,请加参数 -i,要只显示头部,用参数 -I。任何时候,可以使用 -v 命令看curl是怎样工作的,它向服务器发送的所有命令都会显示出来。为了断点续传,可以使用-r参数来指定传输范围。 2、表单(Form)的获取 在WEB页面设计中,form是很重要的元素。Form通常用来收集并向网站提交信息。提交信息的方法有两种,GET方法和POST方法。先讨论GET方法,例如在页面中有这样一段: 那么浏览器上会出现一个文本框和一个标为“OK”的按钮。按下这个按钮,表单就用GET方法向服务器提交文本框的数据。例如原始页面是在 www.hotmail.com/when/birth.html看到的,然后您在文本框中输入1905,然后按OK按钮,那么浏览器的URL现在应该 是:“www.hotmail.com/when/junk.cgi?birthyear=1905&press=OK” 对于这种网页,curl可以直接处理,例如想获取上面的网页,只要输入: curl "www.hotmail.com/when/junk.cgi?birthyear=1905&press=OK" 就可以了。 表单用来提交信息的第二种方法叫做POST方法,POST方法和GET方法的区别在于GET方法使用的时候,浏览器中会产生目标URL,而POST不会。类似GET,这里有一个网页: 浏览器上也会出现一个文本框和一个标为“OK”的按钮。按下这个按钮,表单用POST方法向服务器提交数据。这时的URL是看不到的,因此需要使用特殊的方法来抓取这个页面: curl -d "birthyear=1905&press=OK" www.hotmail.com/when/junk.cgi 这个命令就可以做到。 1995年年末,RFC 1867定义了一种新的POST方法,用来上传文件。主要用于把本地文件上传到服务器。此时页面是这样写的: 对于这种页面,curl的用法不同: curl -F upload=@localfilename -F press=OK [URL] 这个命令的实质是将本地的文件用POST上传到服务器。有关POST还有不少用法,用户可以自己摸索。 3、使用PUT方法。 HTTP协议文件上传的标准方法是使用PUT,此时curl命令使用-T参数: curl -T uploadfile www.uploadhttp.com/receive.cgi 4、有关认证。 curl可以处理各种情况的认证页面,例如下载用户名/密码认证方式的页面(在IE中通常是出现一个输入用户名和密码的输入框): curl -u name:password www.secrets.com 如果网络是通过http代理服务器出去的,而代理服务器需要用户名和密码,那么输入: curl -U proxyuser:proxypassword http://curl.haxx.se 任何需要输入用户名和密码的时候,只在参数中指定用户名而空着密码,curl可以交互式的让用户输入密码。 5、引用。 有些网络资源访问的时候必须经过另外一个网络地址跳转过去,这用术语来说是:referer,引用。对于这种地址的资源,curl也可以下载: curl -e http://curl.haxx.se daniel.haxx.se 6、指定用户客户端。 有些网络资源首先需要判断用户使用的是什么浏览器,符合标准了才能够下载或者浏览。此时curl可以把自己“伪装”成任何其他浏览器: curl -A "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)" [URL] 这个指令表示curl伪装成了IE5.0,用户平台是Windows 2000。(对方服务器是根据这个字串来判断客户端的类型的,所以即使使用AIX也无所谓)。使用: curl -A "Mozilla/4.73 [en] (X11; U; Linux 2.2.15 i686)" [URL] 此时curl变成了Netscape,运行在PIII平台的Linux上了。 7、COOKIES Cookie是服务器经常使用的一种记忆客户信息的方法。如果cookie被记录在了文件中,那么使用命令: curl -b stored_cookies_in_file www.cookiesite.com curl可以根据旧的cookie写出新cookie并发送到网站: curl -b cookies.txt -c newcookies.txt www.cookiesite.com 8、加密的HTTP——HTTPS。 如果是通过OpenSSL加密的https协议传输的网页,curl可以直接访问: curl https://that.secure.server.com 9、http认证。 如果是采用证书认证的http地址,证书在本地,那么curl这样使用: curl -E mycert.pem https://that.secure.server.com 参考读物和注意事项:curl非常博大,用户要想使用好这个工具,除了详细学习参数之外,还需要深刻理解http的各种协议与URL的各个语法。这里推荐几个读物: RFC 2616 HTTP协议语法的定义。 RFC 2396 URL语法的定义。 RFC 2109 Cookie是怎样工作的。 RFC 1867 HTTP如何POST,以及POST的格式 ############################################################# CURL? 嗯,说来话长了~~~~ 这东西现在已经是苹果机上内置的命令行工具之一了,可见其魅力之一斑 1) 二话不说,先从这里开始吧! curl http://www.yahoo.com 回车之后,www.yahoo.com 的html就稀里哗啦地显示在屏幕上了~~~~~ 2) 嗯,要想把读过来页面存下来,是不是要这样呢? curl http://www.yahoo.com > page.html 当然可以,但不用这么麻烦的! 用curl的内置option就好,存下http的结果,用这个option: -o curl -o page.html http://www.yahoo.com 这样,你就可以看到屏幕上出现一个下载页面进度指示。等进展到100%,自然就OK咯 3) 什么什么?!访问不到?肯定是你的proxy没有设定了。 使用curl的时候,用这个option可以指定http访问所使用的proxy服务器及其端口: -x curl -x 123.45.67.89:1080 -o page.html http://www.yahoo.com 4) 访问有些网站的时候比较讨厌,他使用cookie来记录session信息。 像IE/NN这样的浏览器,当然可以轻易处理cookie信息,但我们的curl呢? .. 我们来学习这个option: -D < -- 这个是把http的response里面的cookie信息存到一个特别的文件中去 curl -x 123.45.67.89:1080 -o page.html -D cookie0001.txt http://www.yahoo.com 这样,当页面被存到page.html的同时,cookie信息也被存到了cookie0001.txt里面了 5) 那么,下一次访问的时候,如何继续使用上次留下的cookie信息呢?要知道,很多网站都是靠监视你的cookie信息, 来判断你是不是不按规矩访问他们的网站的。 这次我们使用这个option来把上次的cookie信息追加到http request里面去: -b curl -x 123.45.67.89:1080 -o page1.html -D cookie0002.txt -b cookie0001.txt http://www.yahoo.com 这样,我们就可以几乎模拟所有的IE操作,去访问网页了! 6) 稍微等等~~~~~我好像忘记什么了~~~~~ 对了!是浏览器信息~~~~ 有些讨厌的网站总要我们使用某些特定的浏览器去访问他们,有时候更过分的是,还要使用某些特定的版本~~~~ NND,哪里有时间为了它去找这些怪异的浏览器呢!? 好在curl给我们提供了一个有用的option,可以让我们随意指定自己这次访问所宣称的自己的浏览器信息: -A curl -A "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)" -x 123.45.67.89:1080 -o page.html -D cookie0001.txt http://www.yahoo.com 这样,服务器端接到访问的要求,会认为你是一个运行在Windows 2000上的IE6.0,嘿嘿嘿,其实也许你用的是苹果机呢! 而"Mozilla/4.73 [en] (X11; U; Linux 2.2; 15 i686"则可以告诉对方你是一台PC上跑着的Linux,用的是Netscape 4.73,呵呵呵 7) 另 外一个服务器端常用的限制方法,就是检查http访问的referer。比如你先访问首页,再访问里面所指定的下载页,这第二次访问的referer地址 就是第一次访问成功后的页面地址。这样,服务器端只要发现对下载页面某次访问的referer地址不 是首页的地址,就可以断定那是个盗连 了~~~~~ 讨厌讨厌~~~我就是要盗连~~~~~!! 幸好curl给我们提供了设定referer的option: -e curl -A "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)" -x 123.45.67.89:1080 -e "mail.yahoo.com" -o page.html -D cookie0001.txt http://www.yahoo.com 这样,就可以骗对方的服务器,你是从mail.yahoo.com点击某个链接过来的了,呵呵呵 8) 写着写着发现漏掉什么重要的东西了!----- 利用curl 下载文件 刚才讲过了,下载页面到一个文件里,可以使用 -o ,下载文件也是一样。 比如, curl -o 1.jpg http://cgi2.tky.3web.ne.jp/~zzh/screen1.JPG 这里教大家一个新的option: -O 大写的O,这么用: curl -O http://cgi2.tky.3web.ne.jp/~zzh/screen1.JPG 这样,就可以按照服务器上的文件名,自动存在本地了! 再来一个更好用的。 如果screen1.JPG以外还有screen2.JPG、screen3.JPG、 .、screen10.JPG需要下载,难不成还要让我们写一个script来完成这些操作? 不干! 在curl里面,这么写就可以了: curl -O http://cgi2.tky.3web.ne.jp/~zzh/screen[1-10].JPG 呵呵呵,厉害吧?!~~~ 9) 再来,我们继续讲解下载! curl -O http://cgi2.tky.3web.ne.jp/~{zzh,nick}/[001-201].JPG 这样产生的下载,就是 ~zzh/001.JPG ~zzh/002.JPG ~zzh/201.JPG ~nick/001.JPG ~nick/002.JPG ~nick/201.JPG 够方便的了吧?哈哈哈 咦?高兴得太早了。 由于zzh/nick下的文件名都是001,002 ,201,下载下来的文件重名,后面的把前面的文件都给覆盖掉了~~~ 没关系,我们还有更狠的! curl -o #2_#1.jpg http://cgi2.tky.3web.ne.jp/~{zzh,nick}/[001-201].JPG --这是 ..自定义文件名的下载? --对头,呵呵! #1是变量,指的是{zzh,nick}这部分,第一次取值zzh,第二次取值nick #2代表的变量,则是第二段可变部分---[001-201],取值从001逐一加到201 这样,自定义出来下载下来的文件名,就变成了这样: 原来: ~zzh/001.JPG --- > 下载后: 001-zzh.JPG 原来: ~nick/001.JPG ---> 下载后: 001-nick.JPG 这样一来,就不怕文件重名啦,呵呵 9) 继续讲下载 我们平时在windows平台上,flashget这样的工具可以帮我们分块并行下载,还可以断线续传。 curl在这些方面也不输给谁,嘿嘿 比如我们下载screen1.JPG中,突然掉线了,我们就可以这样开始续传 curl -c -O http://cgi2.tky.3wb.ne.jp/~zzh/screen1.JPG 当然,你不要拿个flashget下载了一半的文件来糊弄我~~~~别的下载软件的半截文件可不一定能用哦~~~ 分块下载,我们使用这个option就可以了: -r 举例说明 比如我们有一个http://cgi2.tky.3web.ne.jp/~zzh/zhao1.mp3 要下载(赵老师的电话朗诵 :D ) 我们就可以用这样的命令: curl -r 0-10240 -o "zhao.part1" http:/cgi2.tky.3web.ne.jp/~zzh/zhao1.mp3 & curl -r 10241-20480 -o "zhao.part1" http:/cgi2.tky.3web.ne.jp/~zzh/zhao1.mp3 & curl -r 20481-40960 -o "zhao.part1" http:/cgi2.tky.3web.ne.jp/~zzh/zhao1.mp3 & curl -r 40961- -o "zhao.part1" http:/cgi2.tky.3web.ne.jp/~zzh/zhao1.mp3 这样就可以分块下载啦。 不过你需要自己把这些破碎的文件合并起来 如果你用UNIX或苹果,用 cat zhao.part* > zhao.mp3就可以 如果用的是Windows,用copy /b 来解决吧,呵呵 上面讲的都是http协议的下载,其实ftp也一样可以用。 用法嘛, curl -u name:passwd ftp://ip:port/path/file 或者大家熟悉的 curl ftp://name:passwd@ip:port/path/file 10) 说完了下载,接下来自然该讲上传咯 上传的option是 -T 比如我们向ftp传一个文件: curl -T localfile -u name:passwd ftp://upload_site:port/path/ 当然,向http服务器上传文件也可以 比如 curl -T localfile http://cgi2.tky.3web.ne.jp/~zzh/abc.cgi 注意,这时候,使用的协议是HTTP的PUT method 刚才说到PUT,嘿嘿,自然让老服想起来了其他几种methos还没讲呢! GET和POST都不能忘哦。 http提交一个表单,比较常用的是POST模式和GET模式 GET模式什么option都不用,只需要把变量写在url里面就可以了 比如: curl http://www.yahoo.com/login.cgi?user &password =12345 而POST模式的option则是 -d 比如,curl -d "user=nickwolfe &password =12345" http://www.yahoo.com/login.cgi 就相当于向这个站点发出一次登陆申请~~~~~ 到底该用GET模式还是POST模式,要看对面服务器的程序设定。 一点需要注意的是,POST模式下的文件上的文件上传,比如 < form method ="POST" enctype ="multipar/form-data" action ="http://cgi2.tky.3web.ne.jp/~zzh/up_file.cgi" > < input type =file name =upload> =submit name =nick value ="go" > form > 这样一个HTTP表单,我们要用curl进行模拟,就该是这样的语法: curl -F upload=@localfile -F nick=go http://cgi2.tky.3web.ne.jp/~zzh/up_file.cgi 罗罗嗦嗦讲了这么多,其实curl还有很多很多技巧和用法 比如 https的时候使用本地证书,就可以这样 curl -E localcert.pem https://remote_server 再比如,你还可以用curl通过dict协议去查字典~~~~~ curl dict://dict.org/d:computer
#! /usr/bin/python # -*- coding: utf-8 -*- def check_id_num(id_num): assert len(id_num) == 18 and id_num[:17].isdigit() factors = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2] remainders = ['1', '0', '*', '9', '8', '7', '6', '5', '4', '3', '2'] result = sum([f*long(n) for f,n in zip(factors, id_num)]) return remainders[result % 11] == id_num[-1]
设置python运行环境的编码参考这里 http://diveintopython.org/xml_processing/unicode.html 《Dive Into Python》 的 Example 9.15. sitecustomize.py # sitecustomize.py # this file can be anywhere in your Python path, # but it usually goes in ${pythondir}/lib/site-packages/ import sys sys.setdefaultencoding('utf-8') SQLAlchemy的问题请参考这里 http://firefish.blog.51cto.com/298258/112794 create_engine(connstr+"?charset=utf-8", encoding='utf8', convert_unicode=True)
不是代码出的问题,是*.pyc文件被改动了。解决方法,删除所有*.pyc文件再运行
以下脚本在CentOS 5 上通过 #!/bin/bash # 切换到root开始安装 su - mkdir /data/Downloads/ chmod -R 777 /data/Downloads/ cd /data/Downloads/ wget http://postfix.it-austria.net/releases/official/postfix-2.7.1.tar.gz wget ftp://ftp.andrew.cmu.edu/pub/cyrus-mail/cyrus-sasl-2.1.23.tar.gz wget ftp://ftp.andrew.cmu.edu/pub/cyrus/cyrus-imapd-2.3.16.tar.gz wget http://www.openssl.org/source/openssl-1.0.0a.tar.gz #创建用户 useradd -M -s /bin/false -p* postfix groupadd postdrop # 安装 tar xzf openssl-1.0.0a.tar.gz cd openssl-1.0.0a ./config --prefix=/usr/local/openssl-1.0.0a shared threads # -fPIC for 64 bit OS make make install ln -s /usr/local/openssl-1.0.0a /usr/local/openssl tar xzf cyrus-sasl-2.1.23.tar.gz cd cyrus-sasl-2.1.23 ./configure --prefix=/usr/local/postfix/cyrus-sasl-2.1.23 \ --enable-login --enable-ntlm make && make install cd .. tar xzf cyrus-imapd-2.3.16.tar.gz cd cyrus-imapd-2.3.16 ./configure --prefix=/usr/local/postfix/cyrus-imapd-2.3.16 --with-lock=fcntl \ --with-sasl=/usr/local/postfix/cyrus-sasl-2.1.23 \ --with-openssl=/usr/local/openssl make && make install cd .. tar xzf postfix-2.7.1.tar.gz cd postfix-2.7.1 make makefiles --always-make CCARGS='-I/usr/local/postfix/cyrus-sasl-2.1.23/include/sasl -I/usr/local/openssl/include -DDEF_CONFIG_DIR=\"/usr/local/postfix/etc\" -DFD_SETSIZE=2048 -DUSE_CYRUS_SASL -DUSE_TLS' \ AUXLIBS='-L/usr/local/postfix/cyrus-sasl-2.1.23/lib/sasl2 -L/usr/local/openssl/lib -L/usr/local/openssl/lib64 -lsasl2 -lssl -lcrypto' make make install #安装过程中需要回答问题,下面三个问题,请使用右边的回答,其他直接按回车用默认值 # [/usr/bin/mailq] /usr/bin/mailq.postfix # [/usr/bin/newaliases] /usr/bin/newaliases.postfix # [/usr/sbin/sendmail] /usr/sbin/sendmail.postfix cd .. # 添加以下内容到main.cf echo [BELOW TEXT] >> /usr/local/postfix/etc/main.cf local_recipient_maps = #请将所有的mail.example.com和example.com替换为您的MX域名 ###############postfix################################# myhostname = mail.example.com myorigin = example.com mydomain = example.com append_dot_mydomain = no mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain #mynetworks = 192.168.1.0/24, 10.0.0.0/24, 127.0.0.0/8 mynetworks = 127.0.0.1 #只接收本机的本地邮件 #body_checks = regexp:/usr/local/postfix/etc/body_checks #用于从邮件中提取信息记录到postfix日志 ############################CYRUS-SASL############################ broken_sasl_auth_clients = yes smtpd_recipient_restrictions=permit_mynetworks,permit_sasl_authenticated,reject_invalid_hostname,reject_non_fqdn_hostname,reject_unknown_sender_domain,reject_non_fqdn_sender,reject_non_fqdn_recipient,reject_unknown_recipient_domain,reject_unauth_pipelining,reject_unauth_destination smtpd_sasl_auth_enable = yes smtpd_sasl_local_domain = $myhostname smtpd_sasl_security_options = noanonymous smtpd_sasl_application_name = smtpd smtpd_banner = Welcome to our $myhostname ESMTP,Warning: Version not Available! # echo [BELOW TEXT] > /usr/local/postfix/etc/smtpd.conf echo "pwcheck_method: saslauthd" >> /usr/local/postfix/etc/smtpd.conf echo "mech_list: PLAIN LOGIN" >> /usr/local/postfix/etc/smtpd.conf # echo [BELOW TEXT] >> /usr/local/postfix/etc/body_checks /\/account\/([a-z_]+)\/veri/ WARN "$1" /verify=3D([0-9a-f]+)/ WARN "$1" # 设置 rm -f /usr/sbin/sendmail ln -s /usr/sbin/sendmail.postfix /usr/sbin/sendmail rm -f /etc/alternatives/mta ln -s /usr/sbin/sendmail.postfix /etc/alternatives/mta rm -f /usr/sbin/saslauthd ln -s /usr/local/postfix/cyrus-sasl-2.1.23/sbin/saslauthd /usr/sbin/saslauthd rm -rf /etc/postfix ln -s /usr/local/postfix/etc /etc/postfix # 启动 /etc/rc.d/init.d/sendmail stop chkconfig sendmail off chkconfig --list sendmail chkconfig saslauthd on chkconfig --list saslauthd /etc/rc.d/init.d/saslauthd start postfix start # 测试,收件人为who@where.com telnet localhost 25 EHLO mail.example.com MAIL FROM:admin@example.com RCPT TO:who@where.com NOTIFY=success,failure DATA subject:Mail test! This is just a mail test!!! . #从日志中统计退回、拒收、超时失败的邮件 #grep "status=bounced" /var/log/maillog | gawk 'match($0,/to=<(.*)>/){print substr($0,RSTART+4,RLENGTH-5)}' #grep "status=deferred" /var/log/maillog | gawk 'match($0,/to=<(.*)>/){print substr($0,RSTART+4,RLENGTH-5)}' #grep "status=expired" /var/log/maillog | gawk 'match($0,/to=<(.*)>/){print substr($0,RSTART+4,RLENGTH-5)}'
Python关于时间日期有两个库datetime和time,于是我们要在四种格式之间转换: datetime.datetime对象 datetime.datetime.now() time.struct_time对象 time.localtime() 字符串 "2010-12-04T10:30:53" 时间戳 1291433453 (一般我们不关心微秒) 列一下它们的转换方法: dt = datetime.datetime(2010, 12, 4, 10, 30, 53) dt = datetime.datetime.strptime("2010-12-04T10:30:53", "%Y-%m-%dT%H:%M:%S") dt.strftime("%Y-%m-%dT%H:%M:%S") -> "2010-12-04T10:30:53" 或者 dt.isoformat().split(".").pop(0) -> "2010-12-04T10:30:53" dt = datetime.datetime.fromtimestamp(1291433453) (?) dt -> 1291433453 t = time.localtime(1291433453) t = dt.timetuple() t = time.strptime("2010-12-04T10:30:53", "%Y-%m-%dT%H:%M:%S") t.strftime("%Y-%m-%dT%H:%M:%S") -> "2010-12-04T10:30:53" long( time.mktime(t) ) -> 1291433453 (?) t -> dt 可以看出,Python没有提供直接的time.struct_time对象到datetime.datetime对象的转换,也没有直接提供datetime.datetime对象到时间戳的转换。另外,Python的两个strftime ,strptime中都没有时间戳的格式化符号。 对time.struct_time对象到datetime.datetime对象的转换,很容易想到通过字符串形式过渡一下: dt = datetime.datetime.strptime(t.strftime("%Y-%m-%dT%H:%M:%S"), "%Y-%m-%dT%H:%M:%S") 更好的方式应该是这样 dt = datetime.datetime(*tuple(t)[:6]) 对于datetime.datetime对象到时间戳的转换,常用做法是通过time.struct_time对象过渡: long(time.mktime(dt.timetuple())) 坏处是要同时用到datetime和time两个模块。 其实可以在datetime内部解决,现在给一个三种格式转为时间戳的方法: def to_timestamp(mytime, format="%Y-%m-%dT%H:%M:%S"): import time from datetime import datetime if isinstance(mytime, time.struct_time): return long(time.mktime(mytime)) elif isinstance(mytime, str): mytime = datetime.strptime(mytime, format) if isinstance(mytime, datetime): #得到一个与时间戳相等的datetime.timedelta对象 delta = mytime - datetime(1970,1,1) utc = delta.days * 86400L + delta.seconds #上面求得delta是一个localtime操作,把时区也考虑进去了,我们要还原 return utc - 8 * 3600 long(dt.strftime("%s"))
因为有个Bash脚本,想根据用户给的日期参数(yyyymmdd格式),得到这个日期的前一天的表示。首先想到的就是date命令,网上搜了一大把,其实多数都是互相抄的,date基本用法原本就会,不能用来解决我的问题。 先说不用date命令的方法: 不嫌麻烦就多用几个判断,解决每月开头、每年开头减去一天的问题,最麻烦的是倒推到上个月最后一天,这一天究竟是28、29还是30、31,还得写个函数。 再说date的基本用法: date +%Y%m%d 这是格式化输出,其他语言多数叫做strftime() date -d "2 days ago" +%s -d可以输入一个日期,不过大多是相对于现在时间,+%s是输出时间戳。 date -d "2010-12-06" +%F -d可以接受ISO格式yyyy-mm-ddTHH:MM:SSZ,也可以接受日期的一些英文格式(月份英文缩写) %F就是%Y%m%d 接着搜到的我不知道的格式用法,当然对我的问题没有帮助: 格式字符中加-可以去掉前面的0,加_把前面的0变成一个空格,举例:date +%-Y%-m%-d 是 2010-12-6 (6前面的0去掉了) date +%_Y%_m%_d 是 2010-12- 6 (6前面有一个空格) 最后是谜底,date可以接受的特殊-d参数: date -d "1970-01-01 UTC 1291622912 seconds" +%s 在前面的日期上面加上这么多秒作为输入。在我的脚本中这么用的: date=$1 #从脚本的第一个参数得到输入日期(格式yyyy-mm-dd或者yyyymmdd) datets=`date -d "$1" +%s` #求出这个日期的时间戳,注意两边的是反引号,Tab键上面那个,下同 yesterts=`expr $datets - 86400` #往前推一天 yesterday=`date -d "1970-01-01 UTC $yesterts seconds" +%Y%m%d` #把它变做输出 我从那里知道的,既不是date的help命令,也不是man文档。而是一个网页 [网址找不着了]
0.目标 安装 pylibmc http://pypi.python.org/packages/source/p/pylibmc/pylibmc-1.1.1.tar.gz#md5=e43c54e285f8d937a3f1a916256ecc85 1.环境 Ubuntu Server 10.04 已经安装了 gcc, python2.6.5和dev包 sudo apt-get install gcc make binutils sudo apt-get install python python-all-dev 2.依赖 libevent http://monkey.org/~provos/libevent-1.4.13-stable.tar.gz [?] zlib http://zlib.net/zlib-1.2.5.tar.gz memcached http://memcached.googlecode.com/files/memcached-1.4.5.tar.gz libmemcached http://launchpad.net/libmemcached/1.0/0.40/+download/libmemcached-0.40.tar.gz 3.安装 tar xzf libevent-1.4.13.tar.gz cd libevent-1.4.13 ./configure --prefix=/opt/lib/libevent-1.4.13 make && sudo make install cd .. tar xzf zlib-1.2.5.tar.gz cd zlib-1.2.5 ./configure --prefix=/opt/lib/zlib-1.2.5 make && sudo make install cd .. tar xzf memcached-1.4.5.tar.gz cd memcached-1.4.5 ./configure --prefix=/opt/memcached-1.4.5 \ --with-libevent=/opt/lib/libevent-1.4.13 make && sudo make install cd .. tar xzf libmemcached-0.40.tar.gz cd libmemcached-0.40 ./configure --prefix=/opt/lib/libmemcached-0.40 \ --with-memcached make && sudo make install ln -s /opt/lib/libmemcached-0.40/lib/libmemcached.so.5 /usr/lib/libmemcached.so.5 cd .. tar xzf pylibmc-1.1.1.tar.gz cd pylibmc-1.1.1 sudo python setup.py build --with-libmemcached=/opt/lib/libmemcached-0.40 sudo python setup.py install cd .. 4.冲突 a) 不安装 python2.6-dev (包含在python-all-dev中)在pylibmc的编译阶段会报错:缺少'Python.h'文件 b) 不建立软链接 libmemcached.so.5 到 /usr/lib会提示 找不到libmemcached.so
E005 2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder. What is the smallest number that is evenly divisible by all of the numbers from 1 to 20? 能被1到20整除的数最小是多少? from prime import Prime def problem5(): pri = Prime(20) #求pri.primes中所有元素的乘积 def mul(x, y): return x*y max_power = reduce(mul, pri.primes, 1) return max_power if __name__=='__main__': print str(problem5()) “能被1到20整除”也就是“能被1到20中的素数整除”,又一个与素数有关的问题
E004 A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 99. Find the largest palindrome made from the product of two 3-digit numbers. 水仙花数是从左向右和从右向左读都相同的自然数。求两个三位数的乘积中最大的水仙花数。 def problem4(): min, max = 100, 999 def isPalindromic(num): if num<=10: return False digits = list(str(num)) revdigs = list(str(num)) revdigs.reverse() return digits==revdigs x = y = avg = max while avg>=min: num = x*y if isPalindromic(num): return x,y,num elif x<=min or y>=max: avg -= 0.5 x = int(avg) y = int(avg+0.5) else: x -= 1 y += 1 if __name__=='__main__': print str(problem4()) 考虑两个三位数乘积最大的是 999x999, (平均数999) 其次是 998x999, (平均数998.5) 再次是 998x998, 997x999, (平均数998) 然后是 997x998, 996x999, (平均数997.5) ......
E003 The prime factors of 13195 are 5, 7, 13 and 29. What is the largest prime factor of the number 600851475143 ? 求600851475143的最大质因子。 今天重写了求素数的方法 # -*- coding:utf-8 -*- class Prime: primes = [2] def __init__(self, maxpri): self.expandList(maxpri) def testNumber(self, x): """ 根据已知素数表用筛法进行测试x """ assert type(1)==type(x) #x必须是整数 if x<2: return False isPri = True for p in self.primes: if p*p>x: #只需测试被sqrt(x)以内的素数整除 break elif 0==x%p: #是合数 isPri = False break return isPri def expandList(self, maxpri, length=None): """ 扩展素数表到接近maxpri,或个数达到length """ x = self.primes[-1] while (True): x += 1 if self.testNumber(x): # Python中改写类成员需要用self.__class__.引用 self.__class__.primes.append(x) #是否达到目标并退出 if maxpri and x>=maxpri: break if length and len(self.primes)>=length: break if __name__ == '__main__': max = 100 pri = Prime(max*max) print str(pri.primes) 有了上面求素数的代码,现在我们可以这样解决问题 from prime import Prime from math import sqrt, floor def problem3(number): lmt = floor(sqrt(number)) factor = 0 pri = Prime(lmt) for p in pri.primes: if 0==number%p: factor = p return factor if __name__ == '__main__': print str(problem3(600851475143))
E002 Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be: 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ... Find the sum of all the even-valued terms in the sequence which do not exceed four million. 找出不大于4,000,000的斐波那契数列中偶数值的总和。 def problem2(): a, b, c = 1, 2, 4*10**6 #掐头 if 0==a%2: sum = 2*a elif 0==b%2: sum = 2*b else: sum = 0 while b<=c: a, b = b, a+b sum += b #去尾 if 0!=b%2: sum -= b if 0!=a%2: sum -= a return sum/2 if __name__=='__main__': print str(problem2())
有个很有意思的网站 ProjectEuler.net ,提出了200多道数学问题,要求读者用计算机求解,不限制所用的计算机语言。 (2008年11月)试着用Python做了几道,挺有意思的。 Add all the natural numbers below one thousand that are multiples of 3 or 5. Find the sum of all the even-valued terms in the Fibonacci sequence which do not exceed four million. Find the largest prime factor of a composite number. Find the largest palindrome made from the product of two 3-digit numbers. What is the smallest number divisible by each of the numbers 1 to 20? E001 If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23. Find the sum of all the multiples of 3 or 5 below 1000. 求1000以下,所有是3或5倍数的数之和。 def problem1(): a, b, c = 3, 5, 999 f = lambda x,lmt=c: x*(lmt/x)*(lmt/x+1)/2 return f(a)+f(b)-f(a*b) if __name__=='__main__': print str(problem1()) 关键是 1000以内能被3整除的数之和是 3(1+2+3+...+333)
昨天在地铁上,突然想到当天是21号,星期一。打开手机看了一下,2001年1月1号正好是星期一。 于是就有一个有趣的问题:那么21世纪中(2001-2100),每个月的1号,同时又是星期一的日子大约有多少天: A. 50 B. 150 C. 350 D. 550 当然,答案是后来设计的。 当时我考虑这个问题,每个月1号是星期一,具有随机性。按概率算,整个世纪共有100*12个1号,1/7是星期一。当时没有用计算器,估计1200/7约为180左右。 这是今天用Python写的代码,运算的结果是172。 from datetime import datetime def month1st_is_monday(start=2001, end=2100): num = 0 for year in range(start, end+1): for mon in (range(1,13)): d = datetime(year, mon, 1) if (1==d.weekday()): num += 1 return num if '__main__' == __name__: print month1st_is_monday() 计算了一下,所有1200个一号里面的分布是这样的 周日 172个 周一 172个 周二 170个 周三 173个 周四 170个 周五 171个 周六 172个
1. JS中数值字符串相加 var a='2.1'; var b='13'; var c=a+b; 则c的值为 2.113,因为+在字符串间是连接符。 如果要求a与b的和,则先要把a、b用parseFloat()或parseInt()转化为浮点数、整数 黑客方法 var c=a-0+b; 因为 – 不管是在数值还是字符串间都是减法运算,对字符串JS会自动把它转化为数值。 2. JS中浮点数的多余的精度 var a= 2.6; var b=2.3; var c = a-b; 那么c的值是多少?0.3?不对,它的值是 0.3000005 0.29999997之类,总之就是不等于0.3。汗! 产生这个情况的原因是浮点数在JS中的存储方式,不仅JS,严格符合ECAMScript规范的脚本语言都有相同的问题。 解决方法 var c = Math.round((a-b)*10)/10; 产生一位小数的精度。 为什么不直接用 (a-b)*10/10?因为当 c=0.29999997时,计算结果变成了我们不想看到的0.2。 3. Jquery中什么时候用$(this),什么时候不存在$(this)? 看看这个例子,点击切换图片。 $(function(){ $(img).bind('click', function(e){ $.ajax({ 'url':'http://www.declab.com/?id='+$(this).val(), 'success':function(html){ $(img).attr('src','http://www.declab.com/images'+html) }, 'cache':false }); }); }); 在这段代码中, 'url'中的 $(this) 和 'success'函数中的$(img) 都是指代码开头被点击的$(img), 但你不可以把第二个$(img)也换成$(this),它属于函数function(html){}的局部变量,已经出了function(e){}的作用域。
当你的硬盘分区不小心被覆盖了,你首先想到的是什么软件? 国产软件DiskGen?在你毁掉分区表之前,你又备份分区表就有用,可惜大多数人都没有这个习惯。如果靠它扫描找回分区表,基本没戏。 俄罗斯的R-Studio,这是很好的扫描并记录每个扇区的软件,可以立即把硬盘信息想、记录下来,防止后面的不当操作导致最终无法恢复。但对几T的硬盘不适用,差不多要原来大小的空间做备份。 WinHex、磁盘武士、DiskTableDoctor(其实是国产)、易我数据库向导,这些都是没有用的。 EasyRecover、RecoverMyFiles之类,这些用来找回个别永久删除的文件,想完整找回整个硬盘的文件不可能,很多找回来的文件都不能用了。 最后隆重介绍TesTDisk,开源软件,可以在Linux和Dos/Windows下使用。上次我把磁盘阵列的分区表给搞没了,在Windows下一看,变成了两个未格式化的分区(总大小超过了2G)。在Google换了N个关键词组合,翻了NN页,终于找到了TestDisk救星。花了几小时扫磁盘,不行,再用高级扫描,整整一天,终于在扫描出来的一大堆分区方案中看到了正确的那个,覆写分区表,全部找回!
今天做一个活儿,需要用到百家姓的拼音,从网上弄了一份百家姓注音,整理了一下,上传共享。 可以从用拼音注册的账号名中推测他(她)姓什么。 话说最复杂的是ji姓和yu姓,都有11个之多。 ji 计/纪/季/吉/嵇/汲/蓟/籍/姬/冀/暨 yu 喻/俞/于/余/禹/虞/郁/於/鬱/鱼/庾
(转自 http://medic.iteye.com/blog/1056515) 2007年我面试了一个被阿里面试后刷掉的电话销售人员,她本来在广州有一份好好的工作,之所以来杭州就是想进阿里。我问她为什么想去阿里工作,她说她被电视上马云的讲话(《赢在中国》)给深深的迷住了,她其实是去拜马云教的。
我的博客即将入驻“云栖社区”,诚邀技术同仁一同入驻。
# -*- coding: utf-8 -*- from flask import request, render_template, Blueprint from flask.views import MethodView from flaskext.principal import RoleNeed, Permission from models import User from utils.pagination import Pagination admin = Permission(RoleNeed('admin')) auth = Permission(RoleNeed('authenticated')) null = Permission(RoleNeed('null')) class SeniorBlueprint(Blueprint): def expose(self, rule, **options): def decorator(v): endpoint = options.pop("endpoint", v.__name__) options["view_func"] = v.as_view(endpoint) options["methods"] = v.methods self.add_url_rule(rule, **options) return v return decorator class SeniorMethodView(MethodView): def paginate(self, view): page_no = int( request.values.get("page", 1) ) page_size = int( request.values.get("page_size", 30) ) return Pagination(view).paginate(page_no, page_size) user_module = SeniorBlueprint("user", __name__) @user_module.expose('list/<role>/') @user_module.expose('list/') class UserAPI(SeniorMethodView): methods = ["GET", "POST"] decorators = [ auth.require(403) ] #要求登录 def get(self, role=""): if role == "admin": params = dict(is_superuser=True, is_active=True) elif role: params = dict(role=role, is_active=True) else: params = dict(is_active=True) view = Session().query(User).filter_by(**params).order_by("-id") page = self.paginate(view) return render_template("user/list.html", page=page) post = get
通常我们在数据库中设计好了多张表,在SQLAlchemy中有个autoload可以自动加载. 让我们的Model都继承自某个虚类,这个虚类在需要时会自动加载一次表结构 生成我们需要的基类,并绑定数据库连接 定义我们的Model,设置表名和外键关联 可以使用session执行SQL了,scoped_session让maker生成的多个session实际上是重用同一个, autocommit=True容易导致Bugs,我们使用默认设置不开启它。 在使用过程中发现几个小时后,数据库连接会断掉而没有重新连接,后来在连接时加入pool_recycle=3600,不知是否有用。 保险起见,可以在models中只生成Session类,要用时再创建实例。 # -*- coding: utf-8 -*- from sqlalchemy import create_engine, Table from sqlalchemy.orm import sessionmaker, scoped_session, relationship, backref from sqlalchemy.ext.declarative import declarative_base, declared_attr from configs.settings import MYSQL_DATABASES, MYSQL_TABLE_PREFIX class Base(object): __abstract__ = True __table_args__ = {"mysql_engine": "InnoDB"} @declared_attr def __table__(cls): name = cls.__tablename__ return Table(name, cls.metadata, autoload=True) engine = create_engine( MYSQL_DATABASES["default"] + "?charset=utf8", encoding="utf-8", pool_size=5, pool_recycle=3600) Base = declarative_base(cls=Base, bind=engine) class Guide(Base): __tablename__ = MYSQL_TABLE_PREFIX + "guide" category = relationship("Category", primaryjoin="Guide.category_id==Category.id", foreign_keys="Guide.category_id", backref="guides") contents = relationship("Content", primaryjoin="Guide.id==Content.guide_id", foreign_keys="Content.guide_id", order_by="Content.section", backref="guide") class Category(Base): __tablename__ = MYSQL_TABLE_PREFIX + "category" class Content(Base): __tablename__ = MYSQL_TABLE_PREFIX + "content" Session = scoped_session(sessionmaker(autoflush=True))