Git Product home page Git Product logo

microacup.github.com's Introduction

microacup.github.com's People

Watchers

 avatar

Forkers

errorlife

microacup.github.com's Issues

SoftReferenceMap使用SoftReference和Map实现缓存

利用SoftReference和ReferenceQueue来搭配从而达到避免oom的功能。

/**
 * 继承map是为了在UIManager中 自由切换 map 和softregerencemap
 */
public class SoftReferenceMap<K, V> extends HashMap<K, V> {
    private static final long serialVersionUID = 1L;
    // 将 V 对象封装成软引用的对象,放置在SoftReferenceMap里面
    private HashMap<K, SoftValue<K, V>> temp;
    //用来存储键入了系统回收队列中的对象, 这里对应的是V
    private ReferenceQueue<V> queue;

    public SoftReferenceMap() {
        super();
        this.temp = new HashMap<K, SoftValue<K, V>>();
        queue = new ReferenceQueue<V>();
    }

    @Override
    public boolean containsKey(Object key) {
        // 清空正在被系统回收队列, 否则可能拿到的SoftReference中可能已经没有了 key对应的对象了
        clearMap();
        return temp.containsKey(key);
    }

    @Override
    public V get(Object key) {
        clearMap();
        SoftValue<K, V> softValue = temp.get(key);
        if (softValue != null) {
            return softValue.get();
        }

        return null;
    }

    @Override
    public V put(K key, V value) {
        SoftValue<K, V> softReference = new SoftValue<K, V>(key, value, queue);
        temp.put(key, softReference);
        return null;
    }

    // 从temp中清空 已经键入了回收队列的 对象(V) 对应的SoftReference
    @SuppressWarnings("unchecked")
    private void clearMap() {
        //从quene中拿到当前已经加入回收队列的最后一个V 
        SoftValue<K, V> softReference = (SoftValue<K, V>) queue.poll();
        while (softReference != null) {
            temp.remove(softReference.key);//拿到这个V对应的key 把他从temp的map中删除
            softReference = (SoftValue<K, V>) queue.poll(); //循环把所有的在回收队列中的值从temp中删除
        }
    }

    //实现一个带键值对的SoftReference, 用来保存一个key供 temp 快速删除 对应的SoftReference
    @SuppressWarnings("hiding")
    private class SoftValue<K, V> extends SoftReference<V> {
        private K key;

        public SoftValue(K k, V v, ReferenceQueue<? super V> q) {
            super(v, q);//把SofrReference注册到Queue中, 系统会在适当时机把 V 加入到回收队列中.
            this.key = k;
        }
    }

}

代码2:Netty中的代码


package io.netty.handler.codec.serialization;

import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
import java.util.Map;

final class SoftReferenceMap<K, V> extends ReferenceMap<K, V> {

    public SoftReferenceMap(Map<K, Reference<V>> delegate) {
        super(delegate);
    }

    @Override
    Reference<V> fold(V value) {
        return new SoftReference<V>(value);
    }

}

package io.netty.handler.codec.serialization;

import java.lang.ref.Reference;
import java.util.Collection;
import java.util.Map;
import java.util.Set;

abstract class ReferenceMap<K, V> implements Map<K, V> {

private final Map<K, Reference<V>> delegate;

protected ReferenceMap(Map<K, Reference<V>> delegate) {
    this.delegate = delegate;
}

abstract Reference<V> fold(V value);

private V unfold(Reference<V> ref) {
    if (ref == null) {
        return null;
    }

    return ref.get();
}

@Override
public int size() {
    return delegate.size();
}

@Override
public boolean isEmpty() {
    return delegate.isEmpty();
}

@Override
public boolean containsKey(Object key) {
    return delegate.containsKey(key);
}

@Override
public boolean containsValue(Object value) {
    throw new UnsupportedOperationException();
}

@Override
public V get(Object key) {
    return unfold(delegate.get(key));
}

@Override
public V put(K key, V value) {
    return unfold(delegate.put(key, fold(value)));
}

@Override
public V remove(Object key) {
    return unfold(delegate.remove(key));
}

@Override
public void putAll(Map<? extends K, ? extends V> m) {
    for (Entry<? extends K, ? extends V> entry : m.entrySet()) {
        delegate.put(entry.getKey(), fold(entry.getValue()));
    }
}

@Override
public void clear() {
    delegate.clear();
}

@Override
public Set<K> keySet() {
    return delegate.keySet();
}

@Override
public Collection<V> values() {
    throw new UnsupportedOperationException();
}

@Override
public Set<Entry<K, V>> entrySet() {
    throw new UnsupportedOperationException();
}

}



参考地址:
> http://my.oschina.net/sfshine/blog/219563
> http://anonsvn.jboss.org/repos/jbosscache/experimental/jsr166/src/jsr166y/ConcurrentReferenceHashMap.java
> https://github.com/netty/netty/blob/5725e804bcfbd0c76e0f11e7911a76970eb06c8c/codec/src/main/java/io/netty/handler/codec/serialization/SoftReferenceMap.java

LayoutInflater的inflate方法用法

LayoutInflater作用是将layout的xml布局文件实例化为View类对象。

获取LayoutInflater的方法有如下三种:

LayoutInflater inflater=(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.main, null);

LayoutInflater inflater = LayoutInflater.from(context); (该方法实质就是第一种方法,可参考源代码)
View layout = inflater.inflate(R.layout.main, null);

LayoutInflater inflater = getLayoutInflater();(在Activity中可以使用,实际上是View子类下window的一个函数)
View layout = inflater.inflate(R.layout.main, null);

setContentView和inflate的区别:

public class MyInflate extends Activity{
    private TextView tv;
    public void OnCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        //setContentView(R.layout.main);
        //tv = (TextView) findViewById(R.id.tv);

        LayoutInflater inflate = LayoutInflater.from(this);
        View view = inflate.inflate(R.layout.main,null);
        setContentView(view);
    }
}

上述注释掉的代码和没有注释掉的代码两种情况是相同的。

区别:

setContentView()一旦调用, layout就会立刻显示UI;而inflate只会把Layout形成一个以view类实现成的对象,有需要时再用setContentView(view)显示出来。一般在activity中通过setContentView()将界面显示出来,但是如果在非activity中如何对控件布局设置操作了,这就需要LayoutInflater动态加载。

public View inflate(int Resourece,ViewGroup root)

作用:填充一个新的视图层次结构从指定的XML资源文件中

reSource:View的layout的ID

root: 生成的层次结构的根视图

return 填充的层次结构的根视图。如果参数root提供了,那么root就是根视图;否则填充的XML文件的根就是根视图。

其余几个重载的inflate函数类似。

Android遇到The specified child already has a parent错误

错误描述:

07-27 17:27:50.453: E/AndroidRuntime(1528): java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.

解决方案:

  • inflater.inflate方法第三个参数传false

    @OverRide
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.user_summary, container, false);
    return view;
    }

问题原因:

  • 通过LayoutInflater实例化的一个布局(View)。被重复添加了两次。而一个View只能有一个父控件。当第二次添加的时候,又要改变这个控件的父控件(虽然是同一个父控件,但是也要通过改变该View的父控件来实现)。运行时又不允许一个有父控件的子控件在有了一个父控件时,改变他的父控件。
  • inflater.inflate(R.layout.user_summary, container, false);第三个参数的意思是是否把当前view加入root中,也就是是自动初始化到界面。而程序中又有其他地方调用了t.add(R.id.menu_frame, mFrag);手动添加了一遍,所以添加了两遍。

类似案例:

LinearLayout listMachines = (LinearLayout) findViewById(R.id.water_level_page_water_level_setting);
 LayoutInflater inflater = LayoutInflater.from(WaterLevelActivity.this);
View tlWaterLevelInfo = inflater.inflate(R.layout.unit_time_water_level_item, null);
listMachines.addView(tlWaterLevelInfo);
listMachines.addView(tlWaterLevelInfo);        //这个地方出错了。

node问题集合

  1. Nodist安装设置,解决被墙
set NODIST_NODE_MIRROR=http://npm.taobao.org/mirrors/node

Android开发问题汇总

  1. 解决IllegalStateException: Can not perform this action after onSaveInstanceState
E/AndroidRuntime(12747): Caused by: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState  
    at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1314)  
    at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1325)  

是在使用FragmentTransition的 commit方法添加一个Fragment的时候出现的,后来在官网找到了相关的
说明:http://developer.android.com/reference/android/app/FragmentTransaction.html#commitAllowingStateLoss()

大致意思是说我使用的 commit方法是在Activity的onSaveInstanceState()之后调用的,这样会出错,因为onSaveInstanceState
方法是在该Activity即将被销毁前调用,来保存Activity数据的,如果在保存玩状态后再给它添加Fragment就会出错。解决办法就
是把commit()方法替换成 commitAllowingStateLoss()就行了,其效果是一样的。

Python使用exe安装第三方包时,找不到版本的解决方案。

This steps work for me with windows 8.1 64bits

The problem is that some module installers look in the wrong place for Python version information.

For example, in the case of this one module, the installer was looking for HKEY_CURRENT_USER\SOFTWARE\Python\PythonCore\3.4 in the registry.

I found that my Python 3.4 installer had placed this information in HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\3.2 instead.

Once you know the reason, solving it is easy.

Open Registry Editor (may need administrator privilege) and export HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\3.4 into a text file. Open the exported .reg file in a text editor and replace the HKEY_LOCAL_MACHINE entries to HKEY_CURRENT_USER.

Add these new entries back to the registry (here is how). The module installer should now be able to proceed without throwing the error.

ref: http://choorucode.com/2012/04/28/python-version-not-found-in-registry-error/

Android笔记之AlarmManager

Android笔记之AlarmManager

介绍:

developer.android.com中这么描述:

Alarms (based on the AlarmManager class) give you a way to perform time-based operations 
outside the lifetime of your application. For example, you could use an alarm to initiate
a long-running operation, such as starting a service once a day to download a weather forecast.

Alarmmanager主要管理硬件时钟。一些与时间相关的应用,如日历,闹钟等需要使用AlarmManager的服务。AlarmManager被为全局定时器 。AlarmManager对象配合Intent使用,可以定时的开启一个Activity,发送一个BroadCast,或者开启一个Service.

它的作用和Timer有点相似。都有两种相似的用法:

  1. 在指定时长后执行某项操作
  2. 周期性的执行某项操作

如果要定时执行的话,要用AlarmManager,这是闹钟服务,Android手机中必须要保证AlarmManager的时钟跟真实时间同步的.所以在 Android手机休眠状态下,AlarmManager时间是不会变慢的.

注:

如果使用Timer和TimerTask开发定时任务外,发现用Timer的休眠了手机后时间会变慢,所以如果要开发时间精准比较高的手机程序还是使用系统自带的AlarmManager吧。

生命周期:

repeating AlarmManager一旦启动就会一直在后台运行(除非执行cancel方法),可以在“应用管理”中看到这个应用状态是正在运行。 **“强行停止”**可以让Alarmmanager停掉。尝试了几种任务管理器, 都只能重置计数器(确实释放内存了),但都无法关闭定时器,只有系统自带的“强行停止”奏效

AlarmManage接口:

// 取消已经注册的与参数匹配的闹铃 
void   cancel(PendingIntent operation)

  //注册一个新的闹铃
void   set(int type, long triggerAtTime, PendingIntent operation)

  //注册一个重复类型的闹铃
void   setRepeating(int type, long triggerAtTime, long interval, PendingIntent operation)

    //设置时区
void   setTimeZone(String timeZone)

5个闹铃类型:

    public static final int ELAPSED_REALTIME
    //当系统进入睡眠状态时,这种类型的闹铃不会唤醒系统。直到系统下次被唤醒才传递它,该闹铃所用的时间是相对时间,是从系统启动后开始计时的,包括睡眠时间,可以通过调用SystemClock.elapsedRealtime()获得。系统值是3    (0x00000003)。

    public static final int ELAPSED_REALTIME_WAKEUP
    //能唤醒系统,用法同ELAPSED_REALTIME,系统值是2 (0x00000002) 。

    public static final int RTC
    //当系统进入睡眠状态时,这种类型的闹铃不会唤醒系统。直到系统下次被唤醒才传递它,该闹铃所用的时间是绝对时间,所用时间是UTC时间,可以通过调用 System.currentTimeMillis()获得。系统值是1 (0x00000001) 。

    public static final int RTC_WAKEUP
    //能唤醒系统,用法同RTC类型,系统值为 0 (0x00000000) 。

    Public static final int POWER_OFF_WAKEUP
    //能唤醒系统,它是一种关机闹铃,就是说设备在关机状态下也可以唤醒系统,所以我们把它称之为关机闹铃。使用方法同RTC类型,系统值为4(0x00000004)。

注意一个重要的参数PendingIntent。这个PendingIntent可以说是 Intent的进一步封装,他既包含了Intent的描述又是Intent行为的执行(这种定义也许不太严格),如果将Intent比作成一个订单的话,PendingIntent更像是一个下订单的人,因为它既要负责将订单发出去,也要负责订单发送后的处理,比如发送成功后要准备验收订单货物,发送失败后要重发还是取消订单等操作。开发者可以通过调用:

getActivity(Context, int, Intent, int)

getBroadcast(Context, int, Intent, int)

getService(Context, int, Intent, int)

三种不同方式来得到一个PendingIntent实例。

getBroadcast——通过该函数获得的PendingIntent将会扮演一个广播的功能,就像调用 Context.sendBroadcast()函数一样。当系统通过它要发送一个intent时要采用广播的形式,并且在该intent中会包含相应的 intent接收对象,当然这个对象我们可以在创建PendingIntent的时候指定,也可以通过ACTION 和CATEGORY等描述让系统自动找到该行为处理对象。

Intent intent = new Intent(AlarmController.this, OneShotAlarm.class);
PendingIntent sender = PendingIntent.getBroadcast(AlarmController.this, 0, intent, 0);

getActivity——通过该函数获得的PendingIntent可以直接启动新的activity, 就像调用 Context.startActivity(Intent)一样.不过值得注意的是要想这个新的Activity不再是当前进程存在的Activity 时。我们在intent中必须使用Intent.FLAG_ACTIVITY_NEW_TASK.

// The PendingIntent to launch our activity if the user selects this notification
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,  new Intent(this, AlarmService.class), 0);

getService——通过该函数获得的PengdingIntent可以直接启动新的Service,就像调用Context.startService()一样。

// Create an IntentSender that will launch our service, to be scheduled
// with the alarm manager.
mAlarmSender = PendingIntent.getService(AlarmService.this,
            0, new Intent(AlarmService.this, AlarmService_Service.class), 0);

更多内容需要了解:

1.PengdingIntent
2.Service
3.BroadcastReceiver
4.intent-filter

参考资料:

Git常用命令备忘

Git配置

git config --global user.name "robbin"   
git config --global user.email "[email protected]"
git config --global color.ui true
git config --global alias.co checkout
git config --global alias.ci commit
git config --global alias.st status
git config --global alias.br branch
git config --global core.editor "mate -w"# 设置Editor使用textmate
git config -l  # 列举所有配置

用户的git配置文件~/.gitconfig

Git常用命令

查看、添加、提交、删除、找回,重置修改文件

git help <command>  # 显示command的help
git show# 显示某次提交的内容
git show $id

git co  -- <file>   # 抛弃工作区修改
git co  .   # 抛弃工作区修改

git add <file>  # 将工作文件修改提交到本地暂存区
git add .   # 将所有修改过的工作文件提交暂存区

git rm <file>   # 从版本库中删除文件
git rm <file> --cached  # 从版本库中删除文件,但不删除文件

git reset <file># 从暂存区恢复到工作文件
git reset -- .  # 从暂存区恢复到工作文件
git reset --hard# 恢复最近一次提交过的状态,即放弃上次提交后的所有本次修改

git ci <file>
git ci .
git ci -a   # 将git add, git rm和git ci等操作都合并在一起做
git ci -am "some comments"
git ci --amend  # 修改最后一次提交记录

git revert <$id># 恢复某次提交的状态,恢复动作本身也创建了一次提交对象
git revert HEAD # 恢复最后一次提交的状态

查看文件diff

git diff <file> # 比较当前文件和暂存区文件差异
git diff
git diff <$id1> <$id2>   # 比较两次提交之间的差异
git diff <branch1>..<branch2> # 在两个分支之间比较 
git diff --staged   # 比较暂存区和版本库差异
git diff --cached   # 比较暂存区和版本库差异
git diff --stat # 仅仅比较统计信息

查看提交记录

git log
git log <file>  # 查看该文件每次提交记录
git log -p <file>   # 查看每次详细修改内容的diff
git log -p -2   # 查看最近两次详细修改内容的diff
git log --stat  # 查看提交统计信息

tig

Mac上可以使用tig代替diff和log,brew install tig

Git 本地分支管理

查看、切换、创建和删除分支

git br -r   # 查看远程分支
git br <new_branch> # 创建新的分支
git br -v   # 查看各个分支最后提交信息
git br --merged # 查看已经被合并到当前分支的分支
git br --no-merged  # 查看尚未被合并到当前分支的分支

git co <branch> # 切换到某个分支
git co -b <new_branch> # 创建新的分支,并且切换过去
git co -b <new_branch> <branch>  # 基于branch创建新的new_branch

git co $id  # 把某次历史提交记录checkout出来,但无分支信息,切换到其他分支会自动删除
git co $id -b <new_branch>  # 把某次历史提交记录checkout出来,创建成一个分支

git br -d <branch>  # 删除某个分支
git br -D <branch>  # 强制删除某个分支 (未被合并的分支被删除的时候需要强制)

分支合并和rebase

git merge <branch>   # 将branch分支合并到当前分支
git merge origin/master --no-ff  # 不要Fast-Foward合并,这样可以生成merge提交

git rebase master <branch>   # 将master rebase到branch,相当于:
git co <branch> && git rebase master && git co master && git merge <branch>

Git补丁管理(方便在多台机器上开发同步时用)

git diff > ../sync.patch # 生成补丁
git apply ../sync.patch  # 打补丁
git apply --check ../sync.patch  # 测试补丁能否成功

Git暂存管理

git stash# 暂存
git stash list   # 列所有stash
git stash apply  # 恢复暂存的内容
git stash drop   # 删除暂存区

Git远程分支管理

git pull # 抓取远程仓库所有分支更新并合并到本地
git pull --no-ff # 抓取远程仓库所有分支更新并合并到本地,不要快进合并
git fetch origin # 抓取远程仓库更新
git merge origin/master  # 将远程主分支合并到本地当前分支
git co --track origin/branch # 跟踪某个远程分支创建相应的本地分支
git co -b <local_branch> origin/<remote_branch>  # 基于远程分支创建本地分支,功能同上

git push # push所有分支
git push origin master   # 将本地主分支推到远程主分支
git push -u origin master# 将本地主分支推到远程(如无远程主分支则创建,用于初始化远程仓库)
git push origin <local_branch>   # 创建远程分支, origin是远程仓库名
git push origin <local_branch>:<remote_branch>  # 创建远程分支
git push origin :<remote_branch>  #先删除本地分支(git br -d <branch>),然后再push删除远程分

Git远程仓库管理

git remote -v# 查看远程服务器地址和仓库名称
git remote show origin   # 查看远程服务器仓库状态
git remote add origin git@github:robbin/robbin_site.git # 添加远程仓库地址
git remote set-url origin [email protected]:robbin/robbin_site.git # 设置远程仓库地址(用于修改远程仓库地址)
git remote rm <repository>   # 删除远程仓库

创建远程仓库

git clone --bare robbin_site robbin_site.git  # 用带版本的项目创建纯版本仓库
scp -r my_project.git [email protected]:~  # 将纯仓库上传到服务器上

mkdir robbin_site.git && cd robbin_site.git && git --bare init # 在服务器创建纯仓库
git remote add origin [email protected]:robbin/robbin_site.git# 设置远程仓库地址
git push -u origin master  # 客户端首次提交
git push -u origin develop  # 首次将本地develop分支提交到远程develop分支,并且track

git remote set-head origin master   # 设置远程仓库的HEAD指向master分支

也可以命令设置跟踪远程库和本地库

git branch --set-upstream master origin/master
git branch --set-upstream develop origin/develop

从robbinfan的网站copy下来的

Learn Python The Hard Way

最近得知一个很好的在线学习Python等的网站:http://learnpythonthehardway.org/ 中文名叫《笨办法学Python》

以动手实践为荣 , 以只看不练为耻;
以打印日志为荣 , 以单步跟踪为耻;
以空格缩进为荣 , 以制表缩进为耻;
以单元测试为荣 , 以人工测试为耻;

以模块复用为荣 , 以复制粘贴为耻;
以多态应用为荣 , 以分支判断为耻;
以Pythonic为荣 , 以冗余拖沓为耻;
以总结分享为荣 , 以跪求其解为耻;

何为“ Hard Way ”?有这么三点:

1. Go through each exercise.
2. Type in each sample exactly.
3. Make it run.

刚开始会有些困难,但要坚持下去,打好基础,学到的不仅仅是这本语言而已。

尤其重要的一点:

Do Not Copy-Paste!

必须逐字逐句手工敲打,如果复制粘贴很容易想当然,练习的要点是锻炼你的手指,大脑和思维。学会如果去读、写、看代码。如果你复制粘贴,你就是在欺骗自己。

比胖子更可恶的是懒惰的胖子!!!

牢记python哲学:
import this

Beautiful is better than ugly. 
Explicit is better than implicit. 
Simple is better than complex. 
Complex is better than complicated. 
Flat is better than nested. 
Sparse is better than dense. 
Readability counts. 
Special cases aren’t special enough to break the rules. 
Although practicality beats purity. 
Errors should never pass silently. 
Unless explicitly silenced. 
In the face of ambiguity, refuse the temptation to guess. 
There should be one– and preferably only one –obvious way to do it. 
Although that way may not be obvious at first unless you’re Dutch. 
Now is better than never. 
Although never is often better than *right* now. 
If the implementation is hard to explain, it’s a bad idea. 
If the implementation is easy to explain, it may be a good idea. 
Namespaces are one honking great idea — let’s do more of those! 

– by Tim Peters

Scrapy 搞起篇

Scrapy 搞起篇(2014年8月30日-8月31日)

开始于:Beijing,Raining,2014-8-30 22:45:00
结束于:2014-8-31 01:46:00

0. 环境

python 2.7.8

windows 8.1 x64

如果接下来用pip安装或者直接安装出现:

UnicodeEncodeError: 'ascii' codec can't encode characters in position 1-5: 
ordinal not in range(128)

需要在Python27\Lib\site-packages 建一个文件sitecustomize.py。原因是pip安装python包会加载用户目录,用户目录恰好是中文的,ascii不能编码。python会自动运行这个文件。

1. Install pip

a. setuptools:

You must start the Powershell with Administrative privileges.
Using Windows 8 or later, it's possible to install with one simple Powershell command. Start up Powershell and paste this command:

(Invoke-WebRequest https://bootstrap.pypa.io/ez_setup.py).Content | python -
https://pip.pypa.io/en/latest/installing.html#install-pip

b. python setup.py install :

下载 pip源码,解压,安装。

E:\Python27\Scripts加入环境变量

2.安装Twisted(必须)

官网,傻瓜安装。

3. 安装w3lib

官方主页:http://pypi.python.org/pypi/w3lib

Github:https://github.com/scrapy/w3lib

4. 安装Zope.Interface (必须)

官网:https://pypi.python.org/pypi/zope.interface/4.1.1#downloads

5. 安装OpenSSL(未成功,但仍然安装了Scrapy)

官网:https://pypi.python.org/pypi/pyOpenSSL

可能会出现error: Setup script exited with error: Unable to find vcvarsall.bat, 需要安装Visual Studio。

如果安装了VS2010或是VS2012可以使用下面的方法解决:
If you have Visual Studio 2010 installed, execute >
SET VS90COMNTOOLS=%VS100COMNTOOLS%
or with Visual Studio 2012 installed >
SET VS90COMNTOOLS=%VS110COMNTOOLS%
python 2.7在setup的时候查找的是VS2008编译的。
For Windows installations: While running setup.py for for package installations Python 2.7 searches for an installed Visual Studio 2008. You can trick Python to use newer Visual Studio by setting correct path in VS90COMNTOOLS environment variable before calling setup.py.

有人说VS2010无效。

建议还是用vs vs2008 c++ ,如果使用的是64位,一定要装pro版vs,因为express版没有64位编译器
或者 :

以下亲测无效

首先安装MinGW(MinGW下载地址:http://sourceforge.net/projects/mingw/files/),在MinGW的安装目录下找到bin的文件夹,找到mingw32-make.exe,复制一份更名为make.exe;

把MinGW的路径添加到环境变量path中,比如我把MinGW安装到D:\MinGW\中,就把D:\MinGW\bin添加到path中;
打开命令行窗口,在命令行窗口中进入到要安装代码的目录下;

输入如下命令 setup.py install build –compiler=mingw32 就可以安装了。

6. 安装lxml(不知道干嘛,也不知是否必须)

官网:https://pypi.python.org/simple/lxml/

下载:lxml-3.3.6.win-amd64-py2.7.exe

7. 安装service_identity

下载:https://pypi.python.org/pypi/service_identity#downloads

8. 安装 Scrapy

下载源码安装,或者:

pip install scrapy

9. 创建工程

参考官方文档:http://doc.scrapy.org/en/latest/intro/tutorial.html

scrapy startproject tutorial

结果如下:

F:\code\python\scrapy-tutorial\tutorial>scrapy crawl dmoz
:0: UserWarning: You do not have a working installation of the service_identi
module: 'No module named service_identity'.  Please install it from <https://
i.python.org/pypi/service_identity> and make sure all of its dependencies are
tisfied.  Without the service_identity module and a recent enough pyOpenSSL t
upport it, Twisted can perform only rudimentary TLS client hostname verificat
.  Many valid certificate/hostname mappings may be rejected.
2014-08-31 01:38:12+0800 [scrapy] INFO: Scrapy 0.24.4 started (bot: tutorial)
2014-08-31 01:38:12+0800 [scrapy] INFO: Optional features available: ssl, htt

2014-08-31 01:38:12+0800 [scrapy] INFO: Overridden settings: {'NEWSPIDER_MODU
: 'tutorial.spiders', 'SPIDER_MODULES': ['tutorial.spiders'], 'BOT_NAME': 'tu
ial'}
2014-08-31 01:38:13+0800 [scrapy] INFO: Enabled extensions: LogStats, TelnetC
ole, CloseSpider, WebService, CoreStats, SpiderState
2014-08-31 01:38:14+0800 [scrapy] INFO: Enabled downloader middlewares: HttpA
Middleware, DownloadTimeoutMiddleware, UserAgentMiddleware, RetryMiddleware,
aultHeadersMiddleware, MetaRefreshMiddleware, HttpCompressionMiddleware, Redi
tMiddleware, CookiesMiddleware, ChunkedTransferMiddleware, DownloaderStats
2014-08-31 01:38:14+0800 [scrapy] INFO: Enabled spider middlewares: HttpError
dleware, OffsiteMiddleware, RefererMiddleware, UrlLengthMiddleware, DepthMidd
are
2014-08-31 01:38:14+0800 [scrapy] INFO: Enabled item pipelines:
2014-08-31 01:38:14+0800 [dmoz] INFO: Spider opened
2014-08-31 01:38:14+0800 [dmoz] INFO: Crawled 0 pages (at 0 pages/min), scrap
0 items (at 0 items/min)
2014-08-31 01:38:14+0800 [scrapy] DEBUG: Telnet console listening on 127.0.0.
023
2014-08-31 01:38:14+0800 [scrapy] DEBUG: Web service listening on 127.0.0.1:6

2014-08-31 01:38:15+0800 [dmoz] DEBUG: Crawled (200) <GET http://www.dmoz.org
mputers/Programming/Languages/Python/Resources/> (referer: None)
2014-08-31 01:38:15+0800 [dmoz] DEBUG: Crawled (200) <GET http://www.dmoz.org
mputers/Programming/Languages/Python/Books/> (referer: None)
2014-08-31 01:38:15+0800 [dmoz] INFO: Closing spider (finished)
2014-08-31 01:38:15+0800 [dmoz] INFO: Dumping Scrapy stats:
        {'downloader/request_bytes': 516,
         'downloader/request_count': 2,
         'downloader/request_method_count/GET': 2,
         'downloader/response_bytes': 16515,
         'downloader/response_count': 2,
         'downloader/response_status_count/200': 2,
         'finish_reason': 'finished',
         'finish_time': datetime.datetime(2014, 8, 30, 17, 38, 15, 497000),
         'log_count/DEBUG': 4,
         'log_count/INFO': 7,
         'response_received_count': 2,
         'scheduler/dequeued': 2,
         'scheduler/dequeued/memory': 2,
         'scheduler/enqueued': 2,
         'scheduler/enqueued/memory': 2,
         'start_time': datetime.datetime(2014, 8, 30, 17, 38, 14, 102000)}
2014-08-31 01:38:15+0800 [dmoz] INFO: Spider closed (finished)

F:\code\python\scrapy-tutorial\tutorial>

并在tutorial目录生成文件:Books和Resources

11. 部署到Scrapyd

文档:http://scrapyd.readthedocs.org/en/latest/overview.html

githu下载安装Scrapyd(略)

注意:scrapyd最好在bash环境下安装和使用,否则在cmd下发布不了,出现以下错误:

'scrapyd' 不是内部或外部命令,也不是可运行的程序或批处理文件。

使用方法:

启动.

bash $下执行命令scrapyd

scrapyd

如果没有执行这一步,直接发布,会出现以下错误:

Packing version 1409469352
Deploying to project "tutorial" in http://localhost:6800/addversion.json
Deploy failed: <urlopen error [Errno 10061] >

发布.

cmd定位到工程目录,执行以下命令启动目录下所有工程:

scrapy deploy

也可以加参数,控制启动工程,这些参数需要在scrapy.cfg文件实现定义,比如:

scrapy.cfg文件:

[deploy:scrapyd2]
url = http://scrapyd.mydomain.com/api/scrapyd/
username = john
password = secret

cmd命令:

scrapy deploy scrapyd2 -p project

启动成功后,出现:

F:\code\python\scrapy-tutorial\tutorial>scrapy deploy
Packing version 1409481980
Deploying to project "tutorial" in http://localhost:6800/addversion.json
Server response (200):
{"status": "ok", "project": "tutorial", "version": "1409481980", "spiders": 1, "
node_name": "Power"}

在url中可以看到当前的监控:

http://localhost:6800/

启动爬虫.

curl http://localhost:6800/schedule.json -d project=default -d spider=somespider

例如:

F:\code\python\scrapy-tutorial\tutorial>curl http://localhost:6800/schedule.json
 -d project=default -d spider=dmoz
{"status": "ok", "jobid": "d0c2844030ff11e49f53206a8a4b80ec", "node_name": "Powe
r"}
F:\code\python\scrapy-tutorial\tutorial>

http://localhost:6800/jobs能看到当前爬虫任务情况

For more information about the API, see the Scrapyd documentation。

11. 常见问题

问题:

Unknown command: crawl

Use "scrapy" to see available commands

解决方法:

需要进入项目目录才能执行该命令。cd  tutorial

问题:

执行scrapy crawl dmoz 后出现Handler': No module named win32api

Handler': DLL load failed: %1 不是有效的 Win32 应用程序

解决方法:

可能是版本问题,提示如下操作:

出现No module named win32api异常,到这里下载当前Python(2.7)对应版本的安装模块:

安装pywin32模块,可在http://sourceforge.net/projects/pywin32/下载:
pywin32-219.win-amd64-py2.7.exe(版本必须与当前python的相同)

问题:

error: Unable to find vcvarsall.bat

解决方法:

建议还是用vs vs2008 c++ ,如果使用的是64位,一定要装pro版vs,因为express版没有64位编译器.

问题:

怎么定时爬取

解决方法:

windows下用任务计划定时执行批处理文件,或者Linux系统定时任务(比如crond)定时执行抓取。

参考:

http://doc.scrapy.org/en/latest/intro/install.html#intro-install

http://www.cnblogs.com/txw1958/archive/2012/07/12/scrapy_installation_introduce.html

http://my.oschina.net/zhangdapeng89/blog/54407

http://www.crifan.com/while_install_scrapy_error_unable_to_find_vcvarsall_bat/

http://blog.csdn.net/changdejie/article/details/18407979

http://www.kankanews.com/ICkengine/archives/94817.shtml

http://blog.chinaunix.net/uid-24567872-id-3925118.html

http://blog.csdn.net/iefreer/article/details/20677943

http://www.oschina.net/translate/build-website-crawler-based-upon-scrapy

http://blog.jobbole.com/73115/

http://www.itdiffer.com/doc-view-727.html

动态加载CSS和JS文件

GIS组件用到了arcgis api中的对象,而这些api文件太大,不好封装到组件里,所以需要动态加载cssjs文件,以便部署到不同的服务器。

在查阅各种资料后发现,动态加载js文件的过程其实可以分为以下两种:同步和异步。

而在这个问题处理之前,需要大概明白这么一件事情:**浏览器如何加载HTML页面?**这是一个比较复杂的问题,各种浏览器的实现方式也不一样,所以HTML页面加载的流程也不完全相同,但整个流程是大致确定的。

关于HTML的加载过程,总体上来说,浏览器会从上往下边加载边解释,同时生成DOM对象,如果遇到外部链接,比如引入js文件,在IE中会开辟一个线程,主线程继续执行;在火狐中会阻塞,知道js文件下载解释执行完成。

总结来看(网上摘录,不保证正确):

浏览器加载显示html的顺序是按下面的顺序进行的:
1、IE下载的顺序是从上到下,渲染的顺序也是从上到下,下载和渲染是同时进行的。
2、在渲染到页面的某一部分时,其上面的所有部分都已经下载完成(并不是说所有相关联的元素都已经下载完)。
3、如果遇到语义解释性的标签嵌入文件(JS脚本,CSS样式),那么此时IE的下载过程会启用单独连接进行下载。
4、并且在下载后进行解析,解析过程中,停止页面所有往下元素的下载。
5、样式表在下载完成后,将和以前下载的所有样式表一起进行解析,解析完成后,将对此前所有元素(含以前已经渲染的)重新进行渲染。
6、JS、CSS中如有重定义,后定义函数将覆盖前定义函数。

那么如何动态加载css或js呢?

代码1:

 function addFile(URL,FileType){
     var oHead = document.getElementsByTagName('HEAD').item(0);
     var addheadfile;
     if(FileType=="js"){
     addheadfile= document.createElement("script");
     addheadfile.type = "text/javascript";
     addheadfile.src=URL;
 }else{
     addheadfile= document.createElement("link");
     addheadfile.type = "text/css";
     addheadfile.rel="stylesheet";
     addheadfile.rev = "stylesheet";
     addheadfile.media = "screen";
     addheadfile.href=URL;
     }
     oHead.appendChild( addheadfile);
 }

用法:

addFile("css/index.css","css");
addFile("js/index.js","js");

很典型的创建动态标签,经过测试发现,上述带码会异步执行,而且在不同浏览器中文件的加载顺序也是不同的。如果两个js直接有依赖关系,这样的加载方式是不行的。

代码2:

var classcodes =[];
window.Import={
    LoadFileList:function(_files,succes){
        var FileArray=[];
        if(typeof _files==="object"){
            FileArray=_files;
        }else{
            if(typeof _files==="string"){
                FileArray=_files.split(",");
            }
        }
        if(FileArray!=null && FileArray.length>0){
            var LoadedCount=0;
            for(var i=0;i< FileArray.length;i++){
                loadFile(FileArray[i],function(){
                    LoadedCount++;
                    if(LoadedCount==FileArray.length){
                        succes();
                    }
                })
            }
        }
        function loadFile(url, success) {
            if (!FileIsExt(classcodes,url)) {
                var ThisType=GetFileType(url);
                var fileObj=null;
                if(ThisType==".js"){
                    fileObj=document.createElement('script');
                    fileObj.src = url;
                    fileObj.type = "text/javascript";
                }else if(ThisType==".css"){
                    fileObj=document.createElement('link');
                    fileObj.href = url;
                    fileObj.type = "text/css";
                    fileObj.rel="stylesheet";
                }
                success = success || function(){};
                fileObj.onload = fileObj.onreadystatechange = function() {
                    if (!this.readyState || 'loaded' === this.readyState || 'complete' === this.readyState) {
                        success();
                        classcodes.push(url)
                    }
                }
                document.getElementsByTagName('head')[0].appendChild(fileObj);
            }else{
                success();
            }
        }
        function GetFileType(url){
            if(url!=null && url.length>0){
                return url.substr(url.lastIndexOf(".")).toLowerCase();
            }
            return "";
        }
        function FileIsExt(FileArray,_url){
            if(FileArray!=null && FileArray.length>0){
                var len =FileArray.length;
                for (var i = 0; i < len; i++) {
                    if (FileArray[i] ==_url) {
                       return true;
                    }
                }
            }
            return false;
        }
        }
    }

用法:

Import.LoadFileList(cssfiles,function(){
      // TODO 成功加载的函数 
}); 

这样加入了一个判断状态是否完成代码,可以这样来嵌套调用:

Import.LoadFileList(cssfiles,function(){
       Import.LoadFileList(jsfile,function(){
             Import.LoadFileList(mainjs,function(){
            });
        })
    });

这样就实现了同步加载JS文件。

也可以使用XMLHttpRequestajax来实现同步加载,实现过程由各位自行脑补。

------------------------无耻的分隔符----------------------------------

引申:如何判断文件加载完成?

CSS文件动态加载(续)—— 残暴的本相

关于html和javascript在浏览器中的加载顺序问题的讨论(zz)

html的加载过程

动态加载外部css或js文件

Javascript在页面加载时的执行顺序

判断一个变量是否定义的方法

nginx 通过ip无法访问目标的解决方案connect() to failed (13: Permission denied) while connecting to upstream

I had a similar issue getting Fedora 20, Nginx, Node.js, and Ghost (blog) to work. It turns out my issue was due to SELinux.

I checked for errors in the SELinux logs:
sudo cat /var/log/audit/audit.log | grep nginx | grep denied
And found that running the following commands fixed my issue:

sudo cat /var/log/audit/audit.log | grep nginx | grep denied | audit2allow -M mynginx
sudo semodule -i mynginx.pp

References:

http://blog.frag-gustav.de/2013/07/21/nginx-selinux-me-mad/ https://wiki.gentoo.org/wiki/SELinux/Tutorials/Where_to_find_SELinux_permission_denial_details http://wiki.gentoo.org/wiki/SELinux/Tutorials/Managing_network_port_labels http://www.linuxproblems.org/wiki/Selinux

http://stackoverflow.com/questions/23948527/13-permission-denied-while-connecting-to-upstreamnginx

tornado输出json总是编码而不是汉字的问题

使用tornado开发rest服务时,需要输出json格式的数据,但是按照经验写入header,写入json(dict格式)数据后,输出的数据中的汉字总是‘u'\u6c49'’这种编码。
苦恼过后,去看web.write的源码,里面是这么写的:

def write(self, chunk):
    """如果你要输出json,那么就传入一个dict就可以了
    """
    if self._finished:
        raise RuntimeError("Cannot write() after finish().  May be caused "
                           "by using async operations without the "
                           "@asynchronous decorator.")
    if isinstance(chunk, dict):
        chunk = escape.json_encode(chunk)
        self.set_header("Content-Type", "application/json; charset=UTF-8")
    chunk = utf8(chunk)
    self._write_buffer.append(chunk)

我操,好简单,它只需要你传入一个dict格式的对象就可以了。其实..escape.json_encode(chunk).嗯,坑爹呢这是...就是这个玩意搞的,好么。

好吧,解决方法也是无比简单,你不去传入一个dict就可以了,真是无比机智的少年啊。

你只需要自己写个方法就解决了:

def render_json(self, data):
    self.set_header("Content-Type", "application/json; charset=utf-8")
    self.write(str(data)) # 传入字符串就可以了嘛

好了。就这样吧,今天是2013年12月31日。女神,你的眼睛。哑铃走起。

MySql用户权限

grant all privileges on *.* to hwalk1@'%' identified by 'hwalk1';
flush privileges;
insert into user (Host,User,Password) values('localhost','shagua',''); 

bin>mysql -u root
mysql> grant 权限1,权限2,…权限n on 数据库名称.表名称 to 用户名@用户地址 identified by ‘连接口令’;

权限1,权限2,…权限n代表select,insert,update,delete,create,drop,index,alter,grant,references,reload,shutdown,process,file等14个权限。
当权限1,权限2,…权限n被all privileges或者all代替,表示赋予用户全部权限。
当数据库名称.表名称被_._代替,表示赋予用户操作服务器上所有数据库所有表的权限。
用户地址可以是localhost,也可以是ip地址、机器名字、域名。也可以用’%'表示从任何地址连接。
‘连接口令’不能为空,否则创建失败。

例如:

mysql>grant select,insert,update,delete,create,drop on vtdc.employee to [email protected] identified by ‘123′;

给来自10.163.225.87的用户joe分配可对数据库vtdc的employee表进行select,insert,update,delete,create,drop等操作的权限,并设定口令为123。

mysql>grant all privileges on vtdc.* to [email protected] identified by ‘123′;

给来自10.163.225.87的用户joe分配可对数据库vtdc所有表进行所有操作的权限,并设定口令为123。

mysql>grant all privileges on *.* to [email protected] identified by ‘123′;

给来自10.163.225.87的用户joe分配可对所有数据库的所有表进行所有操作的权限,并设定口令为123。

mysql>grant all privileges on *.* to joe@localhost identified by ‘123′;

给本机用户joe分配可对所有数据库的所有表进行所有操作的权限,并设定口令为123。

localStorage是不跨域的

例如:在www.host1.com下,localStorage有2条记录;在www.host2.com下,localStorage里看不到这两条记录。

Windows下安装Apache Storm集群

default

环境

1. windows 8.1 x64
2. JDK 1.7u71 x64
3. python 2.7.8 x64
4. zookeeper-3.4.6
5. storm-0.9.3

注意事项

JDK路径不允许有空格,否则启动storm时找不到JAVA_HOME。

安装

总的来讲被比较简单,0.9.1以后的版本,不需要依赖0MQ,在Windows下安装已经被官方支持。只需要安装ZookeeperStrom。Zookeeper是运行Strom的集群。

配置环境变量

JAVA_HOME C:\Java\jdk1.7.0_71
STORM_HOME E:\Storm\storm-0.9.3

Install and Run Zookeeper

下载过程略。

> cd zookeeper-3.4.6
> copy conf\zoo_sample.cfg conf\zoo.cfg
> .\bin\zkServer.cmd

Install Storm

下载过程略。

修改配置文件

修改conf/storm.yaml,去掉注释,例如:

storm.zookeeper.servers: - "127.0.0.1" #默认端口

Nimbus

> cd %STORM_HOME%
> storm nimbus

Supervisor

> cd %STORM_HOME%
> storm supervisor

Storm UI

> cd %STORM_HOME%
> storm ui

http://localhost:8080可以查看当前Storm各组件的运行情况。日志在logs\目录

TODO :接下来

运行storm-starter工程。感谢大家的收看,我们下期再见。

参考资料

1. http://ptgoetz.github.io/blog/2013/12/18/running-apache-storm-on-windows/
2. http://storm.incubator.apache.org/documentation/Setting-up-a-Storm-cluster.html

Android Back和Home键相同效果,返回但不销毁

1.当收到back键消息时,调用moveTaskToBack,这样的效果和按Home一样,程序并没有退出,而是在后台。

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_BACK) {
        moveTaskToBack(true);//true对任何Activity都适用
        return true;
    }
    return super.onKeyDown(keyCode, event);
}

activity中调用 moveTaskToBack (boolean nonRoot)方法即可将activity 退到后台,而不用finish()退出。

参数为false代表只有当前activity是task根,指应用启动的第一个activity时才有效;如果为true则忽略这个限制,任何activity都可以有效。

2.另一种思路,跳转Activity到home

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_BACK) {
        Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.addCategory(Intent.CATEGORY_HOME);
        startActivity(intent);
        return true;
    }
    return super.onKeyDown(keyCode, event);
}

JDBC调用存储过程

图表支持存储过程,需要调用已存在于oracle中的存储过程。附上最简单的java调用带参数的存储过程,其中:第一个参数in参数,第二个参数out参数是游标SYS_REFCURSOR
存储过程实例:

CREATE OR REPLACE PROCEDURE "SEARCHNAME"
(icode in char, P_RESULT_SET OUT SYS_REFCURSOR)
AS
BEGIN
        OPEN P_RESULT_SET FOR
        SELECT * FROM TEST_PROCE WHERE TEST_PROCE.CODE = icode;        
END;

java代码:

package test;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;

public class Test {

    public static void main(String[] args) {
        String url = "jdbc:oracle:thin:@10.2.4.169:1521:orcl";
        Connection conn = null;
        CallableStatement proc = null;

        try {
            Class.forName("oracle.jdbc.driver.OracleDriver");
            conn = DriverManager.getConnection(url,"GIS","GIS");
            proc = conn.prepareCall("{ call searchname(?,?) }"); // 执行存储过程searchname
            proc.setString(1, "1002"); // 设置参数in
            proc.registerOutParameter(2, oracle.jdbc.OracleTypes.CURSOR); // 注册游标
            proc.execute(); // 执行

            ResultSet rs = (ResultSet) proc.getObject(2); //取得结果集
            ResultSetMetaData rsmd = rs.getMetaData();

            while (rs.next()) {
                for (int i = 1; i <= rsmd.getColumnCount(); i++) {
                    String columnName = rsmd.getColumnName(i);
                    String columnValue = rs.getString(columnName);
                    System.out.println(columnName + ":" + columnValue);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

本例在jdk1.5下测试通过。

关键点:
java.sql.CallableStatement;

可自行googlejava.sql.CallableStatement;

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.