精华内容
下载资源
问答
  • python程序怎么封装为可被网页调用的接口?或者有什么其他方法吗?web是用Java写的。
  • python 封装API接口

    万次阅读 2019-04-04 16:21:06
    3.对接口进行封装 import os import tornado.ioloop import tornado.web import tornado.httpserver import logging from tornado.escape import json_decode, json_encode, utf8 from phone_frequency_analysis ...

    1.对一天中通话,按时段进行分析
    输入数据为.txt文件,数据部分展示如下:

    u110107_02169228380_530005_20190228125930_61AA.mp3
    u110107_18895672550_530005_20190228165337_FFFFE06F.mp3
    u110107_18895672550_530005_20190228165433_FFFFE0DC.mp3
    u110107_18895672550_530005_20190228165854_FFFF9CB8.mp3
    u110107_18895672550_530005_20190228180136_FFFFB997.mp3
    u110107_18895672550_530005_20190228194425_14A8.mp3
    u110107_18995436895_530005_20190228143208_FFFF8EDE.mp3
    u110107_58033018_530005_20190228150349_5C59.mp3
    u110108_530006_02160383434_20190228121640_5208.mp3
    u110108_530006_02160383434_20190228134648_3117.mp3
    u110108_530006_02160389247_20190228083435_FFFF803B.mp3
    u110108_530006_02160389247_20190228084107_FFFF8232.mp3
    u110108_530006_02160389247_20190228084154_FFFFCC23.mp3
    u110108_530006_02160389263_20190228120132_4BAC.mp3
    

    2.分析如下,返回数据为每个小时对应的通话量

    import numpy as np
    def phone_frequency_analysis():
        with open("data/mp3_filenames.txt",'r',encoding = "utf-8") as f1:
            mp3_filenames = f1.readlines()
        numbers = 24
        count1 = 0
        count2 = 0
        day = "20190228"
        phone_frequency = np.zeros(numbers)
        for line in mp3_filenames:
            time_string = line.strip().split('_')[-2]
            time_string = int(time_string)
            count1 += 1
            for i in range(numbers):
                if time_string >= int(day+"000000") + 10000 *i and time_string < int(day+"010000") + 10000 * i:
                    phone_frequency[i] += 1
                    count2 += 1
                else:
                    pass
    
        #print("phone_frequency:",phone_frequency.astype(int))
        phone_frequency_map = {}
        phone_frequency_map["phone_frequency"] = phone_frequency.astype(int).tolist()
        print(phone_frequency_map)
        return phone_frequency_map
    
    if __name__ == '__main__':
        phone_frequency_map = phone_frequency_analysis()
        print(phone_frequency_map)
    

    3.对接口进行封装

    import os
    import tornado.ioloop
    import tornado.web
    import tornado.httpserver
    import logging
    from tornado.escape import json_decode, json_encode, utf8
    from phone_frequency_analysis import phone_frequency_analysis
    
    logger = logging.getLogger('mylogger')
    logger.setLevel(logging.DEBUG)
    
    fh = logging.handlers.RotatingFileHandler('python_getDemo.log', maxBytes = 1024*1024*1024, backupCount = 100)
    fh.setLevel(logging.DEBUG)
    
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    fh.setFormatter(formatter)
    
    logger.addHandler(fh)
    
    class ChangeModel(tornado.web.RequestHandler):
        def get(self):
            self.set_header("Access-Control-Allow-Origin", "*")
            self.set_header("Access-Control-Allow-Headers", "x-requested-with")
            self.set_header('Access-Control-Allow-Methods', 'POST, GET, OPTIONS')
            phone_frequency = phone_frequency_analysis()
            result = {
                "phone_frequency": phone_frequency,         
                "code": 0
            }
            self.write(json_encode(result))
    
    def make_app():
        return tornado.web.Application([
            (r"/phoneFrequency", ChangeModel),
        ])
    
    if __name__ =="__main__":
        app = make_app()
        sockets = tornado.netutil.bind_sockets(10031)
        http_server = tornado.httpserver.HTTPServer(app)
        http_server.add_sockets(sockets)
        print("Server Start Ok.....")
        tornado.ioloop.IOLoop.instance().start()
    

    4.查看进程

    ps aux|grep phone_frequency_api.py
    

    返回
    在这里插入图片描述
    5.查看端口

    netstat -anp|grep 10031
    

    在这里插入图片描述
    6.测试
    不带输入参数

    curl http://47.105.196.123:10031/phoneFrequency
    

    如果带有输入参数

    curl http://47.92.225.212:10030/testPrint?query="早安我晚点要去进餐"&EnterpriseID=100000011
    

    返回
    在这里插入图片描述
    7.遇到的问题
    TypeError: array is not JSON serializable
    原因:返回的map里面有个值是numpy array类型
    解决方案:要用tolist()方法将array类型转化为list类型
    在这里插入图片描述
    https://stackoverflow.com/questions/26646362/numpy-array-is-not-json-serializable

    展开全文
  • scrapy开源爬虫框架 封装示例(添加 容器,日志处理) python脚步程序简单封装
  • caffe的python接口封装原理与解析

    千次阅读 2016-06-03 13:49:51
    【说明】:caffe提供了灵活的python接口,那么这些接口是如何实现的,caffe是如何有效的把c++中的方法和类,让我们在python中可以灵活调用的; 【c/c++扩展】:python中调用c/c++称为扩展,扩展的方法有很多; ...

    【说明】:欢迎加入:faster-rcnn 交流群 238138700,caffe提供了灵活的python的接口,那么这些接口是如何实现的,caffe是如何有效的把c++中的方法和类,让我们在python中可以灵活调用的;

    【c/c++扩展】:python中调用c/c++称为扩展,扩展的方法有很多;

    标准的方法是:通过样板来包装c/c++代码,这种是最原始的方式,具体的实现可以参考《python核心编程》--22章,看这章的好处就是可以理解封装的思路是怎样的,为什么可行;

    第二类方法就是借用各种各样的工具来减轻我们的工作量:听得最多的应该是SWIG,应该比较好用;caffe用的不是这个,caffe用的是boost python(能够极大提高c++为python写扩展的效率)

    【跟其他工具的比较】:这一段我是借鉴别人的评述:点击打开链接

    目前有多个工具可以实现跟 Boost.Python 类似的功能,如 SWIG,SIP等。但是它们有很大的不同。SWIG 和 SIP 都定义了一种接口描述语言。我需要先写一个接口描述文件,用于描述我要导出的 C++ 函数和类。然后通过一个翻译器,将接口描述文件翻译成 C++ 程序。最后编译连接生成的 C++ 程序来生成扩展库。而 Boost.Python 用于导出 C++ 函数和类的时候,我需要添加的也是 C++ 的代码,这是 Boost.Python 的最大特点之一。
    SWIG 比较适合用来包装 C 语言程序,最近也开始增强一些对 C++ 的支持,但是到目前还不支持嵌套类等 C++ 特性。SIP 似乎除了用在包装 Qt 库之外,就没几个人用。而 Boost.Python 可能是这三者之间对 C++ 支持最好的一个。不过 Boost.Python 也有缺点,就是它使用了大量模板技巧,因此当要导出的元素比较多时,编译非常慢。不过幸好作为“胶水”,我并不需要经常修改和重编译,而且如果使用预编译头的话可以进一步提高编译速度。
    Boost.Python 的另外一个优点是,它的设计目标就是让 C++ 程序库可以透明地导出到 Python 中去。即在完全不修改原来 C++ 程序的情况下,导出给 Python 用。在这种设计理念下设计出来的 Boost.Python 比同类工具支持了给完善的 C++ 特性,能够最大程度地保证不修改原 C++ 程序。要知道贸然修改别人的程序,往往会带来许多难以察觉的错误。
    基于以上几点,我推荐大家在需要的时候使用 Boost.Python,而不是其它。这也是我写这篇文章的最大动力 :-)。

    【boost python】:

    官网的教程是最好的教材,写的也比较简洁:点击打开链接

    我决定跟着官网的教程走一遍,把需要记录的写下来,建议大家也可以跟着官网教程走一遍;


    【caffe的python接口代码】:caffe的python接口的代码就是在./python/caffe/_caffe.cpp文件中实现的,使用的就是boost python库;


    #include <Python.h>  // NOLINT(build/include_alpha)
    
    // Produce deprecation warnings (needs to come before arrayobject.h inclusion).
    #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
    
    #include <boost/make_shared.hpp>
    #include <boost/python.hpp>
    #include <boost/python/raw_function.hpp>
    #include <boost/python/suite/indexing/vector_indexing_suite.hpp>
    #include <boost/python/enum.hpp>
    #include <numpy/arrayobject.h>
    
    // these need to be included after boost on OS X
    #include <string>  // NOLINT(build/include_order)
    #include <vector>  // NOLINT(build/include_order)
    #include <fstream>  // NOLINT
    
    #include "caffe/caffe.hpp"
    #include "caffe/layers/memory_data_layer.hpp"
    #include "caffe/layers/python_layer.hpp"
    #include "caffe/sgd_solvers.hpp"
    
    // Temporary solution for numpy < 1.7 versions: old macro, no promises.
    // You're strongly advised to upgrade to >= 1.7.
    #ifndef NPY_ARRAY_C_CONTIGUOUS
    #define NPY_ARRAY_C_CONTIGUOUS NPY_C_CONTIGUOUS
    #define PyArray_SetBaseObject(arr, x) (PyArray_BASE(arr) = (x))
    #endif
    
    namespace bp = boost::python;
    
    namespace caffe {
    
    // For Python, for now, we'll just always use float as the type.
    typedef float Dtype;
    const int NPY_DTYPE = NPY_FLOAT32;
    
    // Selecting mode.
    void set_mode_cpu() { Caffe::set_mode(Caffe::CPU); }
    void set_mode_gpu() { Caffe::set_mode(Caffe::GPU); }
    
    // For convenience, check that input files can be opened, and raise an
    // exception that boost will send to Python if not (caffe could still crash
    // later if the input files are disturbed before they are actually used, but
    // this saves frustration in most cases).
    static void CheckFile(const string& filename) {
        std::ifstream f(filename.c_str());
        if (!f.good()) {
          f.close();
          throw std::runtime_error("Could not open file " + filename);
        }
        f.close();
    }
    
    void CheckContiguousArray(PyArrayObject* arr, string name,
        int channels, int height, int width) {
      if (!(PyArray_FLAGS(arr) & NPY_ARRAY_C_CONTIGUOUS)) {
        throw std::runtime_error(name + " must be C contiguous");
      }
      if (PyArray_NDIM(arr) != 4) {
        throw std::runtime_error(name + " must be 4-d");
      }
      if (PyArray_TYPE(arr) != NPY_FLOAT32) {
        throw std::runtime_error(name + " must be float32");
      }
      if (PyArray_DIMS(arr)[1] != channels) {
        throw std::runtime_error(name + " has wrong number of channels");
      }
      if (PyArray_DIMS(arr)[2] != height) {
        throw std::runtime_error(name + " has wrong height");
      }
      if (PyArray_DIMS(arr)[3] != width) {
        throw std::runtime_error(name + " has wrong width");
      }
    }
    
    // Net constructor for passing phase as int
    shared_ptr<Net<Dtype> > Net_Init(
        string param_file, int phase) {
      CheckFile(param_file);
    
      shared_ptr<Net<Dtype> > net(new Net<Dtype>(param_file,
          static_cast<Phase>(phase)));
      return net;
    }
    
    // Net construct-and-load convenience constructor
    shared_ptr<Net<Dtype> > Net_Init_Load(
        string param_file, string pretrained_param_file, int phase) {
      CheckFile(param_file);
      CheckFile(pretrained_param_file);
    
      shared_ptr<Net<Dtype> > net(new Net<Dtype>(param_file,
          static_cast<Phase>(phase)));
      net->CopyTrainedLayersFrom(pretrained_param_file);
      return net;
    }
    
    void Net_Save(const Net<Dtype>& net, string filename) {
      NetParameter net_param;
      net.ToProto(&net_param, false);
      WriteProtoToBinaryFile(net_param, filename.c_str());
    }
    
    void Net_SetInputArrays(Net<Dtype>* net, bp::object data_obj,
        bp::object labels_obj) {
      // check that this network has an input MemoryDataLayer
      shared_ptr<MemoryDataLayer<Dtype> > md_layer =
        boost::dynamic_pointer_cast<MemoryDataLayer<Dtype> >(net->layers()[0]);
      if (!md_layer) {
        throw std::runtime_error("set_input_arrays may only be called if the"
            " first layer is a MemoryDataLayer");
      }
    
      // check that we were passed appropriately-sized contiguous memory
      PyArrayObject* data_arr =
          reinterpret_cast<PyArrayObject*>(data_obj.ptr());
      PyArrayObject* labels_arr =
          reinterpret_cast<PyArrayObject*>(labels_obj.ptr());
      CheckContiguousArray(data_arr, "data array", md_layer->channels(),
          md_layer->height(), md_layer->width());
      CheckContiguousArray(labels_arr, "labels array", 1, 1, 1);
      if (PyArray_DIMS(data_arr)[0] != PyArray_DIMS(labels_arr)[0]) {
        throw std::runtime_error("data and labels must have the same first"
            " dimension");
      }
      if (PyArray_DIMS(data_arr)[0] % md_layer->batch_size() != 0) {
        throw std::runtime_error("first dimensions of input arrays must be a"
            " multiple of batch size");
      }
    
      md_layer->Reset(static_cast<Dtype*>(PyArray_DATA(data_arr)),
          static_cast<Dtype*>(PyArray_DATA(labels_arr)),
          PyArray_DIMS(data_arr)[0]);
    }
    
    Solver<Dtype>* GetSolverFromFile(const string& filename) {
      SolverParameter param;
      ReadSolverParamsFromTextFileOrDie(filename, ¶m);
      return SolverRegistry<Dtype>::CreateSolver(param);
    }
    
    struct NdarrayConverterGenerator {
      template <typename T> struct apply;
    };
    
    template <>
    struct NdarrayConverterGenerator::apply<Dtype*> {
      struct type {
        PyObject* operator() (Dtype* data) const {
          // Just store the data pointer, and add the shape information in postcall.
          return PyArray_SimpleNewFromData(0, NULL, NPY_DTYPE, data);
        }
        const PyTypeObject* get_pytype() {
          return &PyArray_Type;
        }
      };
    };
    
    struct NdarrayCallPolicies : public bp::default_call_policies {
      typedef NdarrayConverterGenerator result_converter;
      PyObject* postcall(PyObject* pyargs, PyObject* result) {
        bp::object pyblob = bp::extract<bp::tuple>(pyargs)()[0];
        shared_ptr<Blob<Dtype> > blob =
          bp::extract<shared_ptr<Blob<Dtype> > >(pyblob);
        // Free the temporary pointer-holding array, and construct a new one with
        // the shape information from the blob.
        void* data = PyArray_DATA(reinterpret_cast<PyArrayObject*>(result));
        Py_DECREF(result);
        const int num_axes = blob->num_axes();
        vector<npy_intp> dims(blob->shape().begin(), blob->shape().end());
        PyObject *arr_obj = PyArray_SimpleNewFromData(num_axes, dims.data(),
                                                      NPY_FLOAT32, data);
        // SetBaseObject steals a ref, so we need to INCREF.
        Py_INCREF(pyblob.ptr());
        PyArray_SetBaseObject(reinterpret_cast<PyArrayObject*>(arr_obj),
            pyblob.ptr());
        return arr_obj;
      }
    };
    
    bp::object Blob_Reshape(bp::tuple args, bp::dict kwargs) {
      if (bp::len(kwargs) > 0) {
        throw std::runtime_error("Blob.reshape takes no kwargs");
      }
      Blob<Dtype>* self = bp::extract<Blob<Dtype>*>(args[0]);
      vector<int> shape(bp::len(args) - 1);
      for (int i = 1; i < bp::len(args); ++i) {
        shape[i - 1] = bp::extract<int>(args[i]);
      }
      self->Reshape(shape);
      // We need to explicitly return None to use bp::raw_function.
      return bp::object();
    }
    
    bp::object BlobVec_add_blob(bp::tuple args, bp::dict kwargs) {
      if (bp::len(kwargs) > 0) {
        throw std::runtime_error("BlobVec.add_blob takes no kwargs");
      }
      typedef vector<shared_ptr<Blob<Dtype> > > BlobVec;
      BlobVec* self = bp::extract<BlobVec*>(args[0]);
      vector<int> shape(bp::len(args) - 1);
      for (int i = 1; i < bp::len(args); ++i) {
        shape[i - 1] = bp::extract<int>(args[i]);
      }
      self->push_back(shared_ptr<Blob<Dtype> >(new Blob<Dtype>(shape)));
      // We need to explicitly return None to use bp::raw_function.
      return bp::object();
    }
    
    BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(SolveOverloads, Solve, 0, 1);
    
    BOOST_PYTHON_MODULE(_caffe) { //给封装的C++模块命名,名称就是_caffe,所以后面编译生成的共享库就是_caffe.so
      // below, we prepend an underscore to methods that will be replaced
      // in Python
    
      bp::scope().attr("__version__") = AS_STRING(CAFFE_VERSION);
    
      // Caffe utility functions //这里使用def封装python中可以调用的C++函数
      bp::def("set_mode_cpu", &set_mode_cpu);
      bp::def("set_mode_gpu", &set_mode_gpu);
      bp::def("set_device", &Caffe::SetDevice);
      bp::def("set_random_seed", &Caffe::set_random_seed);
    
      bp::def("layer_type_list", &LayerRegistry<Dtype>::LayerTypeList);
    
      bp::enum_<Phase>("Phase") //这里封装枚举类型Phase
        .value("TRAIN", caffe::TRAIN)
        .value("TEST", caffe::TEST)
        .export_values();
    
      //封装类Net,添加了构造函数、成员函数、成员变量
      bp::class_<Net<Dtype>, shared_ptr<Net<Dtype> >, boost::noncopyable >("Net",
        bp::no_init)
        .def("__init__", bp::make_constructor(&Net_Init))
        .def("__init__", bp::make_constructor(&Net_Init_Load))
        .def("_forward", &Net<Dtype>::ForwardFromTo)
        .def("_backward", &Net<Dtype>::BackwardFromTo)
        .def("reshape", &Net<Dtype>::Reshape)
        // The cast is to select a particular overload.
        .def("copy_from", static_cast<void (Net<Dtype>::*)(const string)>(
            &Net<Dtype>::CopyTrainedLayersFrom))
        .def("share_with", &Net<Dtype>::ShareTrainedLayersWith)
        .add_property("_blob_loss_weights", bp::make_function(
            &Net<Dtype>::blob_loss_weights, bp::return_internal_reference<>()))
        .def("_bottom_ids", bp::make_function(&Net<Dtype>::bottom_ids,
            bp::return_value_policy<bp::copy_const_reference>()))
        .def("_top_ids", bp::make_function(&Net<Dtype>::top_ids,
            bp::return_value_policy<bp::copy_const_reference>()))
        .add_property("_blobs", bp::make_function(&Net<Dtype>::blobs,
            bp::return_internal_reference<>()))
        .add_property("layers", bp::make_function(&Net<Dtype>::layers,
            bp::return_internal_reference<>()))
        .add_property("_blob_names", bp::make_function(&Net<Dtype>::blob_names,
            bp::return_value_policy<bp::copy_const_reference>()))
        .add_property("_layer_names", bp::make_function(&Net<Dtype>::layer_names,
            bp::return_value_policy<bp::copy_const_reference>()))
        .add_property("_inputs", bp::make_function(&Net<Dtype>::input_blob_indices,
            bp::return_value_policy<bp::copy_const_reference>()))
        .add_property("_outputs",
            bp::make_function(&Net<Dtype>::output_blob_indices,
            bp::return_value_policy<bp::copy_const_reference>()))
        .def("_set_input_arrays", &Net_SetInputArrays,
            bp::with_custodian_and_ward<1, 2, bp::with_custodian_and_ward<1, 3> >())
        .def("save", &Net_Save);
    
      //封装类Blob
      bp::class_<Blob<Dtype>, shared_ptr<Blob<Dtype> >, boost::noncopyable>(
        "Blob", bp::no_init)
        .add_property("shape",
            bp::make_function(
                static_cast<const vector<int>& (Blob<Dtype>::*)() const>(
                    &Blob<Dtype>::shape),
                bp::return_value_policy<bp::copy_const_reference>()))
        .add_property("num",      &Blob<Dtype>::num)
        .add_property("channels", &Blob<Dtype>::channels)
        .add_property("height",   &Blob<Dtype>::height)
        .add_property("width",    &Blob<Dtype>::width)
        .add_property("count",    static_cast<int (Blob<Dtype>::*)() const>(
            &Blob<Dtype>::count))
        .def("reshape",           bp::raw_function(&Blob_Reshape))
        .add_property("data",     bp::make_function(&Blob<Dtype>::mutable_cpu_data,
              NdarrayCallPolicies()))
        .add_property("diff",     bp::make_function(&Blob<Dtype>::mutable_cpu_diff,
              NdarrayCallPolicies()));
    
      //封装类:layer
      bp::class_<Layer<Dtype>, shared_ptr<PythonLayer<Dtype> >,
        boost::noncopyable>("Layer", bp::init<const LayerParameter&>())
        .add_property("blobs", bp::make_function(&Layer<Dtype>::blobs,
              bp::return_internal_reference<>()))
        .def("setup", &Layer<Dtype>::LayerSetUp)
        .def("reshape", &Layer<Dtype>::Reshape)
        .add_property("phase", bp::make_function(&Layer<Dtype>::phase))
        .add_property("type", bp::make_function(&Layer<Dtype>::type));
      bp::register_ptr_to_python<shared_ptr<Layer<Dtype> > >();
    
      bp::class_<LayerParameter>("LayerParameter", bp::no_init);
    
      //封装类solver
      bp::class_<Solver<Dtype>, shared_ptr<Solver<Dtype> >, boost::noncopyable>(
        "Solver", bp::no_init)
        .add_property("net", &Solver<Dtype>::net)
        .add_property("test_nets", bp::make_function(&Solver<Dtype>::test_nets,
              bp::return_internal_reference<>()))
        .add_property("iter", &Solver<Dtype>::iter)
        .def("solve", static_cast<void (Solver<Dtype>::*)(const char*)>(
              &Solver<Dtype>::Solve), SolveOverloads())
        .def("step", &Solver<Dtype>::Step)
        .def("restore", &Solver<Dtype>::Restore)
        .def("snapshot", &Solver<Dtype>::Snapshot);
    
      //封装类SGDSolver,并且该类是Solver的派生类,所以上面封装的Solver的函数和property在该类中也可以调用
      bp::class_<SGDSolver<Dtype>, bp::bases<Solver<Dtype> >,
        shared_ptr<SGDSolver<Dtype> >, boost::noncopyable>(
            "SGDSolver", bp::init<string>());
      bp::class_<NesterovSolver<Dtype>, bp::bases<Solver<Dtype> >,
        shared_ptr<NesterovSolver<Dtype> >, boost::noncopyable>(
            "NesterovSolver", bp::init<string>());
      bp::class_<AdaGradSolver<Dtype>, bp::bases<Solver<Dtype> >,
        shared_ptr<AdaGradSolver<Dtype> >, boost::noncopyable>(
            "AdaGradSolver", bp::init<string>());
      bp::class_<RMSPropSolver<Dtype>, bp::bases<Solver<Dtype> >,
        shared_ptr<RMSPropSolver<Dtype> >, boost::noncopyable>(
            "RMSPropSolver", bp::init<string>());
      bp::class_<AdaDeltaSolver<Dtype>, bp::bases<Solver<Dtype> >,
        shared_ptr<AdaDeltaSolver<Dtype> >, boost::noncopyable>(
            "AdaDeltaSolver", bp::init<string>());
      bp::class_<AdamSolver<Dtype>, bp::bases<Solver<Dtype> >,
        shared_ptr<AdamSolver<Dtype> >, boost::noncopyable>(
            "AdamSolver", bp::init<string>());
    
      bp::def("get_solver", &GetSolverFromFile,
          bp::return_value_policy<bp::manage_new_object>());
    
      //作者把用到的各种vector类型封装了
      // vector wrappers for all the vector types we use
      bp::class_<vector<shared_ptr<Blob<Dtype> > > >("BlobVec")
        .def(bp::vector_indexing_suite<vector<shared_ptr<Blob<Dtype> > >, true>())
        .def("add_blob", bp::raw_function(&BlobVec_add_blob));
      bp::class_<vector<Blob<Dtype>*> >("RawBlobVec")
        .def(bp::vector_indexing_suite<vector<Blob<Dtype>*>, true>());
      bp::class_<vector<shared_ptr<Layer<Dtype> > > >("LayerVec")
        .def(bp::vector_indexing_suite<vector<shared_ptr<Layer<Dtype> > >, true>());
      bp::class_<vector<string> >("StringVec")
        .def(bp::vector_indexing_suite<vector<string> >());
      bp::class_<vector<int> >("IntVec")
        .def(bp::vector_indexing_suite<vector<int> >());
      bp::class_<vector<Dtype> >("DtypeVec")
        .def(bp::vector_indexing_suite<vector<Dtype> >());
      bp::class_<vector<shared_ptr<Net<Dtype> > > >("NetVec")
        .def(bp::vector_indexing_suite<vector<shared_ptr<Net<Dtype> > >, true>());
      bp::class_<vector<bool> >("BoolVec")
        .def(bp::vector_indexing_suite<vector<bool> >());
    
      // boost python expects a void (missing) return value, while import_array
      // returns NULL for python3. import_array1() forces a void return value.
      import_array1();
    }
    
    }  // namespace caffe





















    展开全文
  • 环境:python2.7 docker:一、一个简单的python程序既然是一个简单的python程序,那我们就实现一个简单的加法功能即可。#coding=utf-8 import random def add(aStr,bStr):  map={}  try:  a=float(aStr)  b=...

    环境:python2.7   

    docker:


    一、一个简单的python程序

    既然是一个简单的python程序,那我们就实现一个简单的加法功能即可。

    #coding=utf-8
    import random
    
    
    def add(aStr,bStr):
        map={}
        try:
            a=float(aStr)
            b=float(bStr)
            sum=a+b
            file_name=str(int(random.random()*1000000))+""
            file=open("data/"+file_name+'.txt',"w")
            file.write(str(a)+"+"+str(b)+"="+str(sum))
            file.close()
            map["result"]="OK"
            map["id"]=str(file_name)
        except:
            map["result"]="wrong"
    
    
    
    
        return map
    
    
    if __name__=="__main__":
        print "运行run啊大哥,不是这个"
        map=add("4.5",5.6)
        print map
    

    这个方法实现的功能都能看明白,就是把a和b相加,并且将结果输出在一个文件中,并返回是否运行成功,如果成功则再加上文件的编号(后面那段不管= =)

    二、对外提供一个调用接口

    除了这段代码我们还需要对外提供一个调用接口,我使用tornado开一个web服务来提供接口,这个方法命名为run方法= =

    #coding=utf-8
    
    import tornado.web
    import tornado.ioloop
    from add  import add
    
    #定义处理类
    class Add(tornado.web.RequestHandler):
        #添加一个post请求方式的方法
        def post(self):
            #向响应中,添加数据
            a=self.get_argument('a', '')
            b=self.get_argument('b', '')
            map=add(a,b)
            self.write(map)
    
    def make_app():
        return tornado.web.Application(
            [(r'/add', Add)],
        )
    
    if __name__ == '__main__':
        # 创建一个应用对象
        app = make_app()
        #绑定一个监听端口
        app.listen(8888)
        #启动web程序,开始监听端口的连接
        tornado.ioloop.IOLoop.current().start()

    当我们运行run.py之后,在终端输入命令    curl  -d 'a=3&b=9' 'localhost:8888/add'

    终端返回信息为:{"result": "OK", "id": "808992"}   (这里的ID不一定会相同,只是一个随机数)

    在到同文件下面的data目录即可找到对应的数据文件


    到此,我们已经实现了一个python的简单程序,并使其对外提供了一个接口调用,现在我们要将其打包到docker镜像中并对关键代码(add)进行加密

    三、运行一个ubuntu镜像,对安装好python,vim等以及必要的python包例如tornado(docker 的安装使用就不多说了= =)


    显然我们需要的是第一个镜像,将其pull到本地,即运行docker pull ubuntu


    查看本地镜像docker images 可以看到刚才的镜像


    启动它!并安装一些必要的东西!

    docker run -it c9d990395902 /bin/bash   其中c9d990395902为ubuntu的镜像ID,如果你pull的时候它已经更新过了ID可能产生变化,/bin/bash是使得进入新运行的容器内部

    首先执行apt update更新ubuntu系统


    然后使用apt install python安装python2

    中途会问你有一步是否继续,输入y并回车即可

    输入python能进入如下页面即安装成功,输入exit()回车退出编辑

    使用apt-get install python-pip python-dev build-essential安装pip,注意同样需要y回车


    安装完成后输入pip -V即可查看是否安装成功

    安装vim,命令是apt-get install vim

    导入一些python的包,比如tornado,使用命令pip install tornado


    再比如cython,命令为pip install cython


    至此,我们给这个容器安装完成了python,pip,vim以及导入了两个必要的包

    四、新建文件夹并且把代码复制到容器中

    在根目录运行mkdir add_uncleyiba,新建文件夹add_uncleyiba

    进入add_uncleyiba文件夹,新建目录data,新建文件test.py


    用vim打开test.py

    随便按个键比如a,进入编辑模式,输入print 123,然后按Esc,输入:wq(前面是冒号),然后回车,即为保存

    运行python test.py,测试一下没有问题


    现在新建三个文件,分别叫add.py,run.py,setup.py


    利用vim打开add.py把之前的代码复制进去,同理复制run.py的代码(注意,先进入编辑模式之后再复制)

    复制并保存之后可以利用cat命令查看代码是否有问题

    cat add.py


    我们可以尝试在容器中运行add.py,使用命令python add.py


    看上去也没有问题

    现在vim打开setup.py文件,并输入以下内容

    from distutils.core import setup
    from Cython.Build import cythonize
    
    setup(ext_modules = cythonize(["add.py"]))

    然后保存退出

    运行命令python setup.py build_ext,目的是为了生成add.py文件的so文件,保证源码安全

    我们可以发现新生成了build文件夹


    如图add.so即我们需要的so文件!

    使用mv add.so ../../add.so将它放到外层的文件夹去


    现在我们可以删除一些没有用的东西了,除了add.so,data,run.py,setup.py,其他的都可以删除了


    友情提示:删除命令小心使用= =动图想必都看过了

    图片好像动不起来- -可以去一些水群里面找图。。。

    五、提交镜像,并运行测试

    重新打开一个终端,然后将该容器制作成一个镜像docker commit 248224b7067e add_uncleyiba:1.0


    id 是查看自己的容器id得到的,后面的是你要生成的镜像名字+冒号+版本号

    之后我们查看本地镜像的时候就会发现成圣了add_uncleyiba:1.0这个镜像了

    回到一个任意目录,当然,最好是你之前保存python代码的目录,新建文件夹名字叫data


    然后运行命令

    docker run -itd -p 8899:8888  -v #{local_abs_path}:/add_uncleyiba/data  add_uncleyiba:1.0 python /add_uncleyiba/run.py

    其中#{local_abs_path}改成data文件夹的本地的绝对路径(cd进目录后使用pwd查看)

    出现新的容器ID后使用curl  -d 'a=5&b=7' 'localhost:8888/add'进行访问测试就好了~


    这时候我们可以进入到本地的data文件夹,会发现里面有一个文件名就是刚才返回的id值


    打开即为我们刚才的测试内容


    展开全文
  • Python封装

    千次阅读 2021-04-16 16:46:53
    Python基础之封装 一、什么是封装   在程序设计中,封装(Encapsulation)是对具体对象的一种抽象,即将某些部分隐藏起来,在程序外部看不到,其含义是其他程序无法调用。   要了解封装,离不开“私有化”,就是...

    一、什么是封装

      在程序设计中,封装(Encapsulation)是对具体对象的一种抽象,即将某些部分隐藏起来,在程序外部看不到,其含义是其他程序无法调用。
      要了解封装,离不开“私有化”,就是将类或者是函数中的某些属性限制在某个区域之内,外部无法调用。

    二、为什么要封装

      封装数据的主要原因是:保护隐私(把不想别人知道的东西封装起来)
      封装方法的主要原因是:隔离复杂度(比如:电视机,我们看见的就是一个黑匣子,其实里面有很多电器元件,对于用户来说,我们不需要清楚里面都有些元件,电视机把那些电器元件封装在黑匣子里,提供给用户的只是几个按钮接口,通过按钮就能实现对电视机的操作。)
    提示:在编程语言里,对外提供的接口(接口可理解为了一个入口),就是函数,称为接口函数,这与接口的概念还不一样,接口代表一组接口函数的集合体。

    三、封装分为两个层面

      封装其实分为两个层面,但无论哪种层面的封装,都要对外界提供好访问你内部隐藏内容的接口(接口可以理解为入口,有了这个入口,使用者无需且不能够直接访问到内部隐藏的细节,只能走接口,并且我们可以在接口的实现上附加更多的处理逻辑,从而严格控制使用者的访问)
      第一个层面的封装(什么都不用做):创建类和对象会分别创建二者的名称空间,我们只能用类名.或者obj.的方式去
    访问里面的名字,这本身就是一种封装。

    print(p1.brand) #实例化对象(p1.)
    print(vehicle.tag) #类名(vehicle.)
    -------------输出结果--------------
    永久
    fuel oil
    

      注意:对于这一层面的封装(隐藏),类名.和实例名.就是访问隐藏属性的接口第二个层面的封装:类中把某些属性和方法隐藏起来(或者说定义成私有的),只在类的内部使用、外部无法访问,或者留下少量接口(函数)供外部访问。
      Python中私有化的方法也比较简单,即在准备私有化的属性(包括方法、数据)名字前面加两个下划线即可。
      类中所有双下划线开头的名称如__x都会自动变形成:_类名__x的形式:

    class A:
        __N=0 #类的数据属性就应该是共享的,但是语法上是可以把类的数据属性设置成私有的如__N,会变形为_A__N
        def __init__(self):
            self.__X=10 #变形为self._A__X
        def __foo(self): #变形为_A__foo
            print('from A')
        def bar(self):
            self.__foo() #只有在类内部才可以通过__foo的形式访问到. 
    

    这种自动变形的特点:
      1、类中定义的__x只能在内部使用,如self.__x,引用的就是变形的结果。
      2、这种变形其实正是针对外部的变形,在外部是无法通过__x这个名字访问到的。
      3、在子类定义的__x不会覆盖在父类定义的__x,因为子类中变形成了:_子类名__x,而父类中变形成了:_父类名__x,即双下滑线开头的属性在继承给子类时,子类是无法覆盖的。

    注意:对于这一层面的封装(隐藏),我们需要在类中定义一个函数(接口函数)在它内部访问被隐藏的属性,然后外部就可以使用了

    这种变形需要注意的问题是:
      1、这种机制也并没有真正意义上限制我们从外部直接访问属性,知道了类名和属性名就可以拼出名字:_类名__属性,然后就可以访问了,如a._A__N

    a = A()
    print(a._A__N)
    print(a._A__X)
    print(A._A__N)
    --------输出结果--------
    0
    10
    0
    

      2、变形的过程只在类的定义是发生一次,在定义后的赋值操作,不会变形

    a = A() #实例化对象a
    print(a.__dict__) #打印变形的内容
    a.__Y = 20 #新增Y的值,此时加__不会变形
    print(a.__dict__) #打印变形的内容
    ---------输出结果----------
    {'_A__X': 10}
    {'_A__X': 10, '__Y': 20} #发现后面的Y并没有变形
    

      3、在继承中,父类如果不想让子类覆盖自己的方法,可以将方法定义为私有的

    class A: #这是正常情况
        def fa(self):
            print("from A")
        def test(self):
            self.fa()
     
    class B(A):
        def fa(self):
            print("from B")
     
    b = B()
    b.test()
    --------输出结果----------
    from B
    

    看一下把fa被定义成私有的情况:

    class A: #把fa定义成私有的,即__fa
        def __fa(self): #在定义时就变形为_A__fa
            print("from A")
        def test(self):
            self.__fa() #只会与自己所在的类为准,即调用_A__fa
     
    class B(A):
        def __fa(self): #b调用的是test,跟这个没关系
            print("from B")
     
    b = B()
    b.test()
    -------输出结果---------
    from A
    

    四、特性(property)

    1、什么是特性property

      property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值(就是一个装饰器)

    注意:被property装饰的属性会优先于对象的属性被使用,而被propery装饰的属性,分成三种:property、被装饰的函数名.setter、被装饰的函数名.deleter(都是以装饰器的形式)。

    class room: #定义一个房间的类
        def __init__(self,length,width,high):
            self.length = length #房间的长
            self.width = width #房间的宽
            self.high = high #房间的高
        @property
        def area(self): #求房间的平方的功能
            return self.length * self.width #房间的面积就是:长x宽
        @property
        def perimeter(self): #求房间的周长的功能
            return 2 * (self.length + self.width) #公式为:(长 + 宽)x 2
        @property
        def volume(self): #求房间的体积的功能
            return self.length * self.width * self.high #公式为:长 x 宽 x 高
     
    r1 = room(2,3,4) #实例化一个对象r1
    print("r1.area:",r1.area) #可以像访问数据属性一样去访问area,会触发一个函数的执行,动态计算出一个值
    print("r1.perimeter:",r1.perimeter) #同上,就不用像调用绑定方法一样,还得加括号,才能运行
    print("r1.volume:",r1.volume) #同上,就像是把运算过程封装到一个函数内部,我们不管过程,只要有结果就行
    ------------输出结果---------------
    r1.area: 6
    r1.perimeter: 10
    r1.volume: 24
    

    注意:此时的特性arear、perimeter和volume不能被赋值。

    r1.area = 8 #为特性area赋值
    r1.perimeter = 14 #为特性perimeter赋值
    r1.volume = 24 #为特性volume赋值
    '''
    抛出异常:
        r1.area = 8 #第一个就抛异常了,后面的也一样
    AttributeError: can't set attribute
    '''
    

    2、为什么要用property

      将一个类的函数定义成特性以后,对象再去使用的时候obj.name,根本无法察觉自己的name是执行了一个函数然后计算出来的,这种特性的使用方式遵循了统一访问的原则。

    class people: #定义一个人的类
        def __init__(self,name,sex):
            self.name = name
            self.sex = sex #p1.sex = "male",遇到property,优先用property
     
        @property #查看sex的值
        def sex(self):
            return self.__sex #返回正真存值的地方
     
        @sex.setter #修改sex的值
        def sex(self,value):
            if not isinstance(value,str): #在设定值之前进行类型检查
                raise TypeError("性别必须是字符串类型") #不是str类型时,主动抛出异常
            self.__sex = value #类型正确的时候,直接修改__sex的值,这是值正真存放的地方
                #这里sex前加"__",对sex变形,隐藏。
     
        @sex.deleter #删除sex
        def sex(self):
            del self.__sex
     
    p1 = people("egon","male") #实例化对象p1
    print(p1.sex) #查看p1的sex,此时要注意self.sex的优先级
    p1.sex = "female" #修改sex的值
    print(p1.sex) #查看修改后p1的sex
    print(p1.__dict__) #查看p1的名称空间,此时里面有sex
    del p1.sex #删除p1的sex
    print(p1.__dict__) #查看p1的名称空间,此时发现里面已经没有sex了
    -------------------输出结果--------------------
    male
    female
    {'name': 'egon', '_people__sex': 'female'}
    {'name': 'egon'}
    

      python并没有在语法上把它们三个内建到自己的class机制中,在C++里一般会将所有的所有的数据都设置为私有的,然后提供set和get方法(接口)去设置和获取,在python中通过property方法可以实现。

    五、封装与扩展性

      封装在于明确区分内外,使得类实现者可以修改封装内的东西而不影响外部调用者的代码;而外部使用用者只知道一个接口(函数),只要接口(函数)名、参数不变,使用者的代码永远无需改变。这就提供一个良好的合作基础——或者说,只要接口这个基础约定不变,则代码改变不足为虑。

    #类的设计者
    class room: #定义一个房间的类
        def __init__(self,name,owner,length,width,high):
            self.name = name
            self.owner = owner
            self.__length = length #房间的长
            self.__width = width #房间的宽
            self.__high = high #房间的高
        @property
        def area(self): #求房间的平方的功能
            return self.__length * self.__width #对外提供的接口,隐藏了内部的实现细节,\
                                                # 此时我们想求的是房间的面积就是:长x宽
    

    实例化对象通过接口,调用相关属性得到想要的值:

    #类的使用者
    r1 = room("客厅","michael",20,30,9) #实例化一个对象r1
    print(r1.area) #通过接口使用(area),使用者得到了客厅的面积
    -------------输出结果--------------
    600 #得到了客厅的面积
    

    扩展原有的代码,使功能增加:

    #类的设计者,轻松的扩展了功能,而类的使用者完全不需要改变自己的代码
    class room: #定义一个房间的类
        def __init__(self,name,owner,length,width,high):
            self.name = name #房间名
            self.owner = owner #房子的主人
            self.__length = length #房间的长
            self.__width = width #房间的宽
            self.__high = high #房间的高
        @property
        def area(self): #对外提供的接口,隐藏内部实现
            return self.__length * self.__width,\
                   self.__length * self.__width * self.__high #此时我们增加了求体积,
            # 内部逻辑变了,只需增加这行代码就能简单实现,而且外部调用感知不到,仍然使
            # 用该方法,但是功能已经增加了
    

    对于类的使用者,仍然在调用area接口的人来说,根本无需改动自己的代码,就可以用上新功能:

    #类的使用者
    r1 = room("客厅","michael",20,30,9) #实例化一个对象r1
    print(r1.area) #通过接口使用(area),使用者得到了客厅的面积
    --------------输出结果---------------
    (600, 5400) #得到了新增的功能的值
    
    展开全文
  • 主要介绍了Python实现封装打包自己写的代码,被python import,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
  • 简单的使用Python API封装器来使用matplotlib, plotly, bokeh等绘制图表
  • python封装

    千次阅读 多人点赞 2019-06-17 10:43:17
    封装的目的是,保护隐私,把不想让别人知道的东西封装起来。 定义了Student类及实例化,每个实例都拥有各自的name和score。现在若需要打印一个学生的成绩,可定义函数 print_score(),该函数为类外的函数。 class ...
  • PY++ 自动将你的C++程序接口封装python调用 written by pku_goldenlock at qq.com 引言: 我喜欢C++的速度,我喜欢python的简洁,我相信只用C++,python就可以解决99.99%的问题,那么如何让
  • Python程序设计题库

    万次阅读 多人点赞 2020-03-28 17:39:40
    Python程序设计》题库 一、 填空题 1、 Python安装扩展库常用的是_工具。(pip) 2、 Python标准库math中用来计算平方根的函数是____。(sqrt) 3、 Python程序文件扩展名主要有__和两种,其中后者常用于GUI程序...
  • #环境python3.6# 爬取APP 无忧借条# 通过用户账号密码爬取用户个人信息(我这账号密码已打码)爬虫部分代码# coding:utf8 import hashlib import time import urllib3 import json headers = {'Accept': ' */*', '...
  • Python接口自动化之requests请求封装

    千次阅读 热门讨论 2021-07-27 13:41:51
    在上一篇Python接口自动化测试系列文章:Python接口自动化之Token详解及应用,介绍token基本概念、运行原理及在自动化中接口如何携带token进行访问。 以下主要介绍如何封装请求。 还记得我们之前写的get请求、...
  • python笔记(写接口程序基本规范)

    千次阅读 2019-04-14 22:39:54
    简单接口时,可以使用rest framework封装好的功能 class CourseViewSet(mixins.ListModelMixin,mixins.RetrieveModelMixin,GenericViewSet): queryset = models.Course.objects.all() serializer_class = ...
  • 完整的框架源码下载...一、Python+unittest+requests+HTMLTestRunner 完整的接口自动化测试框架搭建_00——框架结构简解 首先配置好开发环境,下载安装Python并...
  • 我是用Windows下的pycharm开发,写了一个函数,如何把这个函数封装起来,然后可以在另外一个项目导入之后直接使用接口进行调用,如何实现这个功能?希望有个具体代码例子来给我讲解,谢谢
  • python模型restful接口

    2018-08-31 13:47:14
    python读取oracle数据库,封装简单模型,提供restful接口,供其他程序调用
  • python学习——Python基础之封装

    万次阅读 2018-04-13 18:39:11
    直到看到这篇文章,详细的讲了python函数、类的封装,并用具体的例子来举例说明,可以说是很好的一篇文章了,特转载过来。原文链接:https://www.cnblogs.com/Michael–chen/p/6740455.html一、什么是封装程序设计...
  • 如何将你的python程序制作为第三方API接口可供任何人调用 1.导入flask相应模块 from flask import Flask//falsk库中有很多模块需根据具体需要确定其他模块 2.Flask架构 app = Flask(__name__)//获取实例 @app.route...
  • 本文使用python对Bmob REST API的基本增删改查接口进行封装,方便在小程序开发时批量插入原始数据。 常用操作函数封装 #!/usr/bin/python # coding:utf-8 # Bmob后端云基本REST API封装 import requests import json...
  • Python对接Java Rest接口简例

    千次阅读 2020-03-19 16:20:42
    文章目录前言 前言 其实大部分接口服务都应该是与语言无关,只是部分重量级后端的...本文就仅仅介绍下Python向Java接口发送请求的一个简短过程,主要是Python代码,Java接口服务涉及到embed-tomcat,懒得展示。 ...
  • Python扩展程序

    千次阅读 2018-05-31 16:35:51
    Python的C语言扩展学习 Python的C语言扩展学习 1. 什么情况需要扩展python 2. 扩展python的缺点 ...注:主要用C语言作为例子扩展python程序 1. 什么情况需要扩展python 1)需要 Python 没有的额外功能:比如...
  • 关于QGIS Python API 解密C ++文档 组织QGIS Python库 qgis.core包 地图和地图图层 协调参考系统 矢量图层 显示矢量数据 访问矢量数据 空间索引 栅格图层 显示栅格数据 访问栅格数据 其他有用的qgis....
  • Python Flask编写API接口

    千次阅读 2019-11-17 02:57:24
    最近在用Pyhon写测试工具平台,编写...在编写工具的过程中,无可避免的需要写一些后端接口供前端调用,以下为常见的几种获取接口入参的方法 from flask import Flask, request, jsonify app = Flask(__name__) ...
  • 我们编写的Python代码会调用内置的Tkinter,Tkinter封装了访问Tk的接口; Tk是一个图形库,支持多个操作系统,使用Tcl语言开发; Tk会调用操作系统提供的本地GUI接口,完成最终的GUI。 所以,我们的代码只需要...
  • python调用dll文件接口

    万次阅读 2017-07-09 23:16:33
    使用python中的ctypes模块可以很方便的调用windows的dll(也包括linux下的so等文件),下面将详细的讲解这个模块(以windows平台为例子),当然我假设你们已经对windows下怎么写一个DLL是没有问题的。   引入ctypes...
  • gRPC python封装深度学习算法教程

    千次阅读 多人点赞 2019-05-25 11:39:39
    最近需要提供一个包含多个神经网络推理的python代码供gRPC调用,即我需要在这个主程序的基础上封装一个支持gRPC的服务端(server)。本教程的目的在于通过简单的代码,来帮助有需求的朋友使用python来构建属于自己的...
  • 使用flask封装,简单来讲就是将python文件引入flask。这样的结果就是在网页上输入一个url就能得到结果。下面就讲如何进行实现。 2. 任务1:求两数之和 2.1 代码讲解 新建一个server.py的文件,文件中代码如下所示: ...
  • 浅谈 Python 程序和 C 程序的整合 Python 是一种用于快速开发软件的编程语言,它的语法比较简单,易于掌握,但存在执行速度慢的问题,并且在处理某些问题时存在不足,如对计算机硬件系统的访问,对媒体文件...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 69,290
精华内容 27,716
关键字:

python程序如何封装成接口

python 订阅