前端工程师

最近一个月,快成前端工程师了。

自从开始用BS解决现在的一些问题,就在补各种前端知识,从我买书的节奏就能看出来我对这个问题了解的深入程度。

第一次——ASP.NET入门经典,这时还没意识到前端的重要性,觉得用默认的模板,弄弄后端就OK了。结果这本真的是入门经典,介绍了WebForm,MVC,WebAPI,但是并没有结构性的深入。

第二次——ASP.NET MVC 5高级编程(第5版) & HTML5+CSS3从入门到精通,时隔一周发现已经用MVC就继续用下去,而且也算好学,要单独买一本介绍MVC实现的。另外在用Razor写View的时候,如何让页面看起来不这么难看也需要学习一些css的知识,还要补补HTML的知识。结果后端的问题基本上是解决了,但是一些功能又必须由前端实现(jQuery),而且那本HTML5+CSS3真的是只介绍HTML5和CSS3,完全没讲我想知道的……。

第三次——和第二次隔了10天,这次基本把问题都解决了,首先是Bootstrap入门经典,ASPNET?MVC5集成的是Bootstrap 3.0,实际上了解css是必要的,但是并不能解决我对排版的需求,直接看这个更方便……然后是Web设计与前端开发秘籍:HTML CSS JavaScript jQuery 构建网站,二本套装,讲这四个东西,这是我最近买的书了印刷排版最良心的,如果时间够,从头到尾看下来估计都不会有什么问题,和看网页+PPT效果一样。最后还买了本精通Python网络爬虫:核心技术、框架与项目实战,有些数据要从内网的网页上爬下来,为了图省事准备学学scrapy。

最近几个礼拜弄这些自己不擅长的东西,压力也比较大,也解决了不少问题,元旦过后有时间再整理一下解决的过程,纪录下来。

Python与DotNet交互环境的搭建以及一些问题

之前一直工作在.NET环境下使用C#,在稍微接触了Python以后被迷住了,实际上到现在除了一个演示滤波的小玩具其他什么也没做,不过参考之前的一些经历,觉得把环境搭好比较重要,方便以后随时地开始玩(造)。
在经历了开始的兴奋阶段后,开始琢磨我可以用这个做些什么,当然对我日常工作很有帮助,但是鉴于我的工作大部分时间要在客户的工作站上完成,所以有了以下需求:
1.需要打包成exe部署到客户端。
2.需要可以和C#交互以便复用之前的一些工作,避免重复开发引起的功能不兼容,以及使用对方没有的功能。

解决方案有3个(未完全测试):

1.IronPython,在.NET下实现Python,这样可以在Python中使用所有的.NET库,当然支持所有Python语法。
2.Microsoft Scripting功能以及IronPython.dll,实际上是在.NET程序中加入了脚本支持功能。
3.CPython+Python for .NET,实际上通过一个接口可以在Python中调用.NET下的CLR,最后再用py2exe打包。

先声明:环境搭建好后还没有经过完全测试,没办法保证可以部署到其他设备上正常使用。会慢慢找机会测试。

方案一——将IronPython集成到.NET开发环境:

首先安装IronPython,安装好后可以使用自带的或其他IDE,我试了Eclipse+PyDev,和SharpDevelop,PyDev不支持可视化图形界面,而SharpDevelop没办法加BreakPoint(不知道是不是我不会设置,求大神帮助)。

一个简单的例子如下:

import sys
sys.path.append("C:\Program Files (x86)\IronPython 2.7\Lib")
sys.path.append("C:\\Program Files (x86)\\IronPython 2.7\\lib\\site-packages")
sys.path.append(r"C:\Program Files (x86)\IronPython 2.7")
sys.path.append(r"C:\Program Files (x86)\IronPython 2.7\DLLs");
sys.path.append(r"C:\Python27\Lib\site-packages")
import clr
clr.AddReference('mtrand.dll')
clr.AddReference('System.Windows.Forms')
clr.AddReference('System.Drawing')
#clr.AddReference('SPInterface')
clr.AddReference('System.IO')
clr.AddReference('System')


from System.Diagnostics import Trace
from System import Console
#import SPInterface as SP
import numpy as np

print 'Hello World'

如果有多种语言的经验,这里比较好理解
sys.path.append类似C编译时的头文件Include路径
clr.AddReference就是.NET里的添加引用
而from System.Diagnostics import Trace则是类似于C#里的
using System.Diagnostics

里面注释掉的几行是我在C#之前写的库,经测试可以正常使用(而且我的库依赖mathdotnet,在同文件夹下貌似自动识别了)。

优点:比较方便,更偏向于.NET,虽然使用的是Python语法。可以很方便的搭建界面。

缺点:由于不兼容CPython,所以很多库用不了,numpy刚刚支持没多久,而matplotlib不支持,实际上感觉完全不能发挥Python的优点。

方案二——在.NET开发环境使用Python脚本:

第一步同上,安装IronPython,在安装文件夹下有Platforms\Net40文件夹,在.NET项目中引用其中的Microsoft.Scripting.dll和IronPython.dll,可以去网上搜搜例子,就可以在代码调用Python脚本了,一个简单的例子:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using IronPython.Hosting;

namespace testIron2
{
   public partial class Form1 : Form
    {
        Microsoft.Scripting.Hosting.ScriptEngine engine;
        public Form1()
        {
            InitializeComponent();
            var source =
@"
import clr
clr.AddReference('mtrand.dll')

def SysPath():
    import sys
    return sys.path
def ImportNumpy():
    import numpy
            ";

            engine = Python.CreateEngine();

            var sp = engine.GetSearchPaths();
            sp.Add(@"C:\Program Files (x86)\IronPython 2.7");
            sp.Add(@"C:\Program Files (x86)\IronPython 2.7\DLLs");
            sp.Add(@"C:\Program Files (x86)\IronPython 2.7\Lib");
            sp.Add(@"C:\Program Files (x86)\IronPython 2.7\Lib\site-packages");
            engine.SetSearchPaths(sp);

            var scope = engine.CreateScope();
            var ops = engine.Operations;

            engine.Execute(source, scope);
            dynamic py = scope;

            // Calling into IronPython works fine + sys.path looks correct
            dynamic syspath = py.SysPath();

            // EXCEPTION when we try to "import numpy":
            // "The type initializer for 'NumpyDotNet.NpyCoreApi' threw an exception.",
            // "Unable to load DLL 'NpyAccessLib': The specified module could not be found. (Exception from HRESULT: 0x8007007E)"
            dynamic numpy = py.ImportNumpy();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            engine.Execute(textBox1.Text);
        }
    }
}

这段代码是当时在网上找的,很抱歉忘记原始链接了,里面的注释应该是原作者遇到的问题,我遇到了应该是相同的,异常信息是无法读取库,原因是没有mtrand.dll文件,stack overflow上有解答,貌似是因为C编译库的问题,所以要在Python命令字符串中加入

clr.AddReference('mtrand.dll')

可以看出来,和方案一其实是一样的,所以优点是熟悉C#代码的可以尽量的用C#,脚本只是辅助方便现场调试修改。
貌似所有在IronPython下安装的库会有DLL版,这意味着我在纯C#下可以用numpy了?还没有测试。

缺点:所有方案一的缺点,而且Python代码无法调试,只有看异常信息然后从头运行。

方案三:在有.NET环境下安装Python for .NET

这个是目前看起来最方便的,只需要装一个库,就可以用类似IronPython的方式来调用.NET环境,包括我自己的库。同时保留所有之前的功能。简单例子如下:

# encoding: utf-8
'''
Created on 2014年5月14日

@author: zcxsun
'''
# import sys
#sys.path.append(r"C:\Qt\Projects\sp_reader\sp_reader\bin\Debug")

import clr
# clr.AddReference('SPInterface')

from System import String
#import SPInterface as SP

a = String('   a,b,c,d,e,f,g   ')
b = a.Trim()
c = String(b).Split(',')
for i in c:
    print i
# SP.SP_Path.folder_name = r'C:\Users\Public\Documents\Zeiss\CALYPSO\sp_filter\conf\spiConf.xml'
# SP.SPI.init()
# for i in SP.SPI.elements:
#     print i.identifier

print 'finish'

注释部分是调用我自己库的代码,需要注意的是很多地方需要显式转换,所以不能用类似a.Trim().Split(‘,’)这样的语法,只能String(a.Trim()).Split(‘,’)这样。因为用type(String(‘ a,b,c ‘).Trim())得到的类型不是Trim应该返回的String类型,而是<type ‘unicode’>

这个感觉应该是最方便的,在Eclipse下显示良好,调试良好。不确定的是py2exe后效果如何。

结论:目前感觉方案2针对我的情况是最优的,方案3则是用来实现功能测试用最方便的,所以未来的短期计划是用PyDev调用一些自己的库,用来设计和实现算法和功能。实验好了后在C#中实现,然后将脚本功能放在文件中调用。

当然,这样的性能应该是有一定问题的,不过对于我的情况是够了。