• 关于 is_file函数 的搜索结果

问题

HybridDB for MySQL中尚未支持的MySQL函数有什么

云栖大讲堂 2019-12-01 21:27:42 1440 浏览量 回答数 0

回答

这里的一个重要说明是,重要的不是函数创建的顺序,而是函数调用完成的时间。 以下列代码为例: def add_one(new): return my_add(new, 1) def my_add(x, y): return x + y my_var = 2 print("The value of my_var is: {}".format(my_var)) my_var = add_one(my_var) print("The value of my_var is: {}".format(my_var)) 它的收益率 这是因为在调用add_one函数时,两个函数都已经存在了。但是如果在定义my_add之前尝试调用add_one… def add_one(new): return my_add(new, 1) my_var = 2 print("The value of my_var is: {}".format(my_var)) my_var = add_one(my_var) print("The value of my_var is: {}".format(my_var)) def my_add(x, y): return x + y 我们得到: The value of my_var is: 2 Traceback (most recent call last): File "c:\Users\wundermahn\Desktop\Stack.py", line 6, in <module> my_var = add_one(my_var) File "c:\Users\J39304\Desktop\Stack.py", line 2, in add_one return my_add(new, 1) NameError: name 'my_add' is not defined 查看Python脚本中函数的顺序是否重要?更多的

kun坤 2019-12-27 17:13:31 0 浏览量 回答数 0

问题

osscsdkwindowsv0.0.7不能编译成动态库吗?

zxywd 2019-12-01 21:14:54 6520 浏览量 回答数 1

试用中心

为您提供0门槛上云实践机会,企业用户最高免费12个月

回答

其中bug存在两个方面, 1、在windowns中,当文件只有只读属性时,is_writeable()函数才返回false,当返回true时,该文件不一定是可写的。 如果是目录,在目录中新建文件并通过打开文件来判断; 如果是文件,可以通过打开文件(fopen),来测试文件是否可写。 2、在Unix中,当php配置文件中开启safe_mode时(safe_mode=on),is_writeable()同样不可用。 读取配置文件是否safe_mode是否开启。 /** * Tests for file writability * * is_writable() returns TRUE on Windows servers when you really can't write to * the file, based on the read-only attribute. is_writable() is also unreliable * on Unix servers if safe_mode is on. * * @access private * @return void */if ( ! function_exists('is_really_writable')) { function is_really_writable($file) { // If we're on a Unix server with safe_mode off we call is_writable if (DIRECTORY_SEPARATOR == '/' AND @ini_get("safe_mode") == FALSE) { return is_writable($file); } // For windows servers and safe_mode "on" installations we'll actually // write a file then read it. Bah... if (is_dir($file)) { $file = rtrim($file, '/').'/'.md5(mt_rand(1,100).mt_rand(1,100)); if (($fp = @fopen($file, FOPEN_WRITE_CREATE)) === FALSE) { return FALSE; } fclose($fp); @chmod($file, DIR_WRITE_MODE); @unlink($file); return TRUE; } elseif ( ! is_file($file) OR ($fp = @fopen($file, FOPEN_WRITE_CREATE)) === FALSE) { return FALSE; } fclose($fp); return TRUE; } }

珍宝珠 2019-12-02 03:16:42 0 浏览量 回答数 0

回答

首先 看到网上说的 $filename = ‘test.txt’ if ( is_writable($name) ) { file_put_contents($filename,”i am the contents”); }else { echo “can not write”; } 用这个 is_writable函数判断能否写入。。 就这个is_writable($name) 函数,我也不懂为何,其实我不加这层判断,实际上是可以写入的。但是,一直就是返回 “can not write“。。。 最后 我把判断删了 才发现其实可以写入 作者:kingsley-sun 来源:CSDN 原文:https://blog.csdn.net/qq_31739317/article/details/73928037 版权声明:本文为博主原创文章,转载请附上博文链接! 首先 看到网上说的 $filename = ‘test.txt’ if ( is_writable($name) ) { file_put_contents($filename,”i am the contents”); }else { echo “can not write”; } 用这个 is_writable函数判断能否写入。。 就这个is_writable($name) 函数,我也不懂为何,其实我不加这层判断,实际上是可以写入的。但是,一直就是返回 “can not write“。。。 最后 我把判断删了 才发现其实可以写入

搞么罗 2019-12-02 01:40:09 0 浏览量 回答数 0

问题

函数中按位异或操作的作用是啥?

小旋风柴进 2019-12-01 20:08:57 1153 浏览量 回答数 1

问题

PyTest中是否有直接将命令行参数传递给conftest.py的方法?

kun坤 2019-12-25 22:04:45 3 浏览量 回答数 1

问题

Python 有没有一种方法可以在限定类中的函数必须返回特定数据类型的内容?

is大龙 2020-03-24 21:39:34 11 浏览量 回答数 1

回答

详细解答可以参考官方帮助文档OSS MEDIA C SDK 客户端部分支持将接收到的H.264、AAC封装为TS、M3U8格式后写入OSS,除了基础接口外,还提供封装好的录播、直播接口。 接口HLS相关封装接口都位于oss_media_hls_stream.h中,目前提供的接口有: oss_media_hls_stream_openoss_media_hls_stream_writeoss_media_hls_stream_close 下面详细介绍各个接口的功能和注意事项 基础结构体介绍/** * OSS MEDIA HLS STREAM OPTIONS的描述信息 */typedef struct oss_media_hls_stream_options_s { int8_t is_live; char *bucket_name; char *ts_name_prefix; char *m3u8_name; int32_t video_frame_rate; int32_t audio_sample_rate; int32_t hls_time; int32_t hls_list_size;} oss_media_hls_stream_options_t;/** * OSS MEDIA HLS STREAM的描述信息 */typedef struct oss_media_hls_stream_s { const oss_media_hls_stream_options_t *options; oss_media_hls_file_t *ts_file; oss_media_hls_file_t *m3u8_file; oss_media_hls_frame_t *video_frame; oss_media_hls_frame_t *audio_frame; oss_media_hls_m3u8_info_t *m3u8_infos; int32_t ts_file_index; int64_t current_file_begin_pts; int32_t has_aud; aos_pool_t *pool;} oss_media_hls_stream_t; 注: is_live,是否是直播模式,直播模式的时候M3U8文件里面只最新的几个ts文件信息bucket_name,存储HLS文件的存储空间名称ts_name_prefix,TS文件名称的前缀m3u8_name,M3U8文件名称video_frame_rate,视频数据的帧率audio_sample_rate,音频数据的采样率hls_time,每个ts文件最大持续时间hls_list_size,直播模式时在M3U8文件中最多保留的ts文件个数 打开HLS stream文件/** * @brief 打开一个oss hls文件 * @param[in] auth_func 授权函数,设置access_key_id/access_key_secret等 * @param[in] options 配置信息 * @return: * 返回非NULL时成功,否则失败 */oss_media_hls_stream_t* oss_media_hls_stream_open(auth_fn_t auth_func, const oss_media_hls_stream_options_t *options); 注: 示例代码参考:GitHub 关闭HLS stream文件/** * @brief 关闭HLS stream文件 */int oss_media_hls_stream_close(oss_media_hls_stream_t *stream); 注: 示例代码参考:GitHub 写HLS stream文件/** * @brief 写入视频和音频数据 * @param[in] video_buf 视频数据 * @param[in] video_len 视频数据的长度,可以为0 * @param[in] audio_buf 音频数据 * @param[in] audio_len 音频数据的长度,可以为0 * @param[in] stream HLS stream * @return: * 返回0时表示成功 * 否则, 表示出现了错误 */int oss_media_hls_stream_write(uint8_t *video_buf, uint64_t video_len, uint8_t *audio_buf, uint64_t audio_len, oss_media_hls_stream_t *stream); 示例程序: static void write_video_audio_vod() { int ret; int max_size = 10 * 1024 * 1024; FILE *h264_file, *aac_file; uint8_t *h264_buf, *aac_buf; int h264_len, aac_len; oss_media_hls_stream_options_t options; oss_media_hls_stream_t *stream; /* 设置HLS stream的参数值 */ options.is_live = 0; options.bucket_name = "<your buckete name>"; options.ts_name_prefix = "vod/video_audio/test"; options.m3u8_name = "vod/video_audio/vod.m3u8"; options.video_frame_rate = 30; options.audio_sample_rate = 24000; options.hls_time = 5; /* 打开HLS stream */ stream = oss_media_hls_stream_open(auth_func, &options); if (stream == NULL) { printf("open hls stream failed.\n"); return; } /* 创建两个buffer用来存储音频和视频数据 */ h264_buf = malloc(max_size); aac_buf = malloc(max_size); /* 读取一段视频数据和音频数据,然后调用接口写入OSS */ { h264_file = fopen("/path/to/video/1.h264", "r"); h264_len = fread(h264_buf, 1, max_size, h264_file); fclose(h264_file); aac_file = fopen("/path/to/audio/1.aac", "r"); aac_len = fread(aac_buf, 1, max_size, aac_file); fclose(aac_file); ret = oss_media_hls_stream_write(h264_buf, h264_len, aac_buf, aac_len, stream); if (ret != 0) { printf("write vod stream failed.\n"); return; } } /* 再读取一段视频数据和音频数据,然后调用接口写入OSS */ { h264_file = fopen("/path/to/video/2.h264", "r"); h264_len = fread(h264_buf, 1, max_size, h264_file); fclose(h264_file); aac_file = fopen("/path/to/audio/1.aac", "r"); aac_len = fread(aac_buf, 1, max_size, aac_file); fclose(aac_file); ret = oss_media_hls_stream_write(h264_buf, h264_len, aac_buf, aac_len, stream); if (ret != 0) { printf("write vod stream failed.\n"); return; } } /* 写完数据后,关闭HLS stream */ ret = oss_media_hls_stream_close(stream); if (ret != 0) { printf("close vod stream failed.\n"); return; } /* 释放资源 */ free(h264_buf); free(aac_buf); printf("convert H.264 and aac to HLS vod succeeded\n");} 注: 目前的录播、直播接口都支持只有视频,只有音频,同时有音视频等。示例代码参考:GitHub目前的录播、直播接口比较初级,用户如果有高级需求,可以模拟这两个接口,使用基础接口自助实现高级定制功能。可以通过示例程序观看效果

2019-12-01 23:15:00 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档OSS MEDIA C SDK 客户端部分支持将接收到的H.264、AAC封装为TS、M3U8格式后写入OSS,除了基础接口外,还提供封装好的录播、直播接口。 接口HLS相关封装接口都位于oss_media_hls_stream.h中,目前提供的接口有: oss_media_hls_stream_openoss_media_hls_stream_writeoss_media_hls_stream_close 下面详细介绍各个接口的功能和注意事项 基础结构体介绍/** * OSS MEDIA HLS STREAM OPTIONS的描述信息 */typedef struct oss_media_hls_stream_options_s { int8_t is_live; char *bucket_name; char *ts_name_prefix; char *m3u8_name; int32_t video_frame_rate; int32_t audio_sample_rate; int32_t hls_time; int32_t hls_list_size;} oss_media_hls_stream_options_t;/** * OSS MEDIA HLS STREAM的描述信息 */typedef struct oss_media_hls_stream_s { const oss_media_hls_stream_options_t *options; oss_media_hls_file_t *ts_file; oss_media_hls_file_t *m3u8_file; oss_media_hls_frame_t *video_frame; oss_media_hls_frame_t *audio_frame; oss_media_hls_m3u8_info_t *m3u8_infos; int32_t ts_file_index; int64_t current_file_begin_pts; int32_t has_aud; aos_pool_t *pool;} oss_media_hls_stream_t; 注: is_live,是否是直播模式,直播模式的时候M3U8文件里面只最新的几个ts文件信息bucket_name,存储HLS文件的存储空间名称ts_name_prefix,TS文件名称的前缀m3u8_name,M3U8文件名称video_frame_rate,视频数据的帧率audio_sample_rate,音频数据的采样率hls_time,每个ts文件最大持续时间hls_list_size,直播模式时在M3U8文件中最多保留的ts文件个数 打开HLS stream文件/** * @brief 打开一个oss hls文件 * @param[in] auth_func 授权函数,设置access_key_id/access_key_secret等 * @param[in] options 配置信息 * @return: * 返回非NULL时成功,否则失败 */oss_media_hls_stream_t* oss_media_hls_stream_open(auth_fn_t auth_func, const oss_media_hls_stream_options_t *options); 注: 示例代码参考:GitHub 关闭HLS stream文件/** * @brief 关闭HLS stream文件 */int oss_media_hls_stream_close(oss_media_hls_stream_t *stream); 注: 示例代码参考:GitHub 写HLS stream文件/** * @brief 写入视频和音频数据 * @param[in] video_buf 视频数据 * @param[in] video_len 视频数据的长度,可以为0 * @param[in] audio_buf 音频数据 * @param[in] audio_len 音频数据的长度,可以为0 * @param[in] stream HLS stream * @return: * 返回0时表示成功 * 否则, 表示出现了错误 */int oss_media_hls_stream_write(uint8_t *video_buf, uint64_t video_len, uint8_t *audio_buf, uint64_t audio_len, oss_media_hls_stream_t *stream); 示例程序: static void write_video_audio_vod() { int ret; int max_size = 10 * 1024 * 1024; FILE *h264_file, *aac_file; uint8_t *h264_buf, *aac_buf; int h264_len, aac_len; oss_media_hls_stream_options_t options; oss_media_hls_stream_t *stream; /* 设置HLS stream的参数值 */ options.is_live = 0; options.bucket_name = "<your buckete name>"; options.ts_name_prefix = "vod/video_audio/test"; options.m3u8_name = "vod/video_audio/vod.m3u8"; options.video_frame_rate = 30; options.audio_sample_rate = 24000; options.hls_time = 5; /* 打开HLS stream */ stream = oss_media_hls_stream_open(auth_func, &options); if (stream == NULL) { printf("open hls stream failed.\n"); return; } /* 创建两个buffer用来存储音频和视频数据 */ h264_buf = malloc(max_size); aac_buf = malloc(max_size); /* 读取一段视频数据和音频数据,然后调用接口写入OSS */ { h264_file = fopen("/path/to/video/1.h264", "r"); h264_len = fread(h264_buf, 1, max_size, h264_file); fclose(h264_file); aac_file = fopen("/path/to/audio/1.aac", "r"); aac_len = fread(aac_buf, 1, max_size, aac_file); fclose(aac_file); ret = oss_media_hls_stream_write(h264_buf, h264_len, aac_buf, aac_len, stream); if (ret != 0) { printf("write vod stream failed.\n"); return; } } /* 再读取一段视频数据和音频数据,然后调用接口写入OSS */ { h264_file = fopen("/path/to/video/2.h264", "r"); h264_len = fread(h264_buf, 1, max_size, h264_file); fclose(h264_file); aac_file = fopen("/path/to/audio/1.aac", "r"); aac_len = fread(aac_buf, 1, max_size, aac_file); fclose(aac_file); ret = oss_media_hls_stream_write(h264_buf, h264_len, aac_buf, aac_len, stream); if (ret != 0) { printf("write vod stream failed.\n"); return; } } /* 写完数据后,关闭HLS stream */ ret = oss_media_hls_stream_close(stream); if (ret != 0) { printf("close vod stream failed.\n"); return; } /* 释放资源 */ free(h264_buf); free(aac_buf); printf("convert H.264 and aac to HLS vod succeeded\n");} 注: 目前的录播、直播接口都支持只有视频,只有音频,同时有音视频等。示例代码参考:GitHub目前的录播、直播接口比较初级,用户如果有高级需求,可以模拟这两个接口,使用基础接口自助实现高级定制功能。可以通过示例程序观看效果

2019-12-01 23:15:00 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档OSS MEDIA C SDK 客户端部分支持将接收到的H.264、AAC封装为TS、M3U8格式后写入OSS,除了基础接口外,还提供封装好的录播、直播接口。 接口HLS相关封装接口都位于oss_media_hls_stream.h中,目前提供的接口有: oss_media_hls_stream_openoss_media_hls_stream_writeoss_media_hls_stream_close 下面详细介绍各个接口的功能和注意事项 基础结构体介绍/** * OSS MEDIA HLS STREAM OPTIONS的描述信息 */typedef struct oss_media_hls_stream_options_s { int8_t is_live; char *bucket_name; char *ts_name_prefix; char *m3u8_name; int32_t video_frame_rate; int32_t audio_sample_rate; int32_t hls_time; int32_t hls_list_size;} oss_media_hls_stream_options_t;/** * OSS MEDIA HLS STREAM的描述信息 */typedef struct oss_media_hls_stream_s { const oss_media_hls_stream_options_t *options; oss_media_hls_file_t *ts_file; oss_media_hls_file_t *m3u8_file; oss_media_hls_frame_t *video_frame; oss_media_hls_frame_t *audio_frame; oss_media_hls_m3u8_info_t *m3u8_infos; int32_t ts_file_index; int64_t current_file_begin_pts; int32_t has_aud; aos_pool_t *pool;} oss_media_hls_stream_t; 注: is_live,是否是直播模式,直播模式的时候M3U8文件里面只最新的几个ts文件信息bucket_name,存储HLS文件的存储空间名称ts_name_prefix,TS文件名称的前缀m3u8_name,M3U8文件名称video_frame_rate,视频数据的帧率audio_sample_rate,音频数据的采样率hls_time,每个ts文件最大持续时间hls_list_size,直播模式时在M3U8文件中最多保留的ts文件个数 打开HLS stream文件/** * @brief 打开一个oss hls文件 * @param[in] auth_func 授权函数,设置access_key_id/access_key_secret等 * @param[in] options 配置信息 * @return: * 返回非NULL时成功,否则失败 */oss_media_hls_stream_t* oss_media_hls_stream_open(auth_fn_t auth_func, const oss_media_hls_stream_options_t *options); 注: 示例代码参考:GitHub 关闭HLS stream文件/** * @brief 关闭HLS stream文件 */int oss_media_hls_stream_close(oss_media_hls_stream_t *stream); 注: 示例代码参考:GitHub 写HLS stream文件/** * @brief 写入视频和音频数据 * @param[in] video_buf 视频数据 * @param[in] video_len 视频数据的长度,可以为0 * @param[in] audio_buf 音频数据 * @param[in] audio_len 音频数据的长度,可以为0 * @param[in] stream HLS stream * @return: * 返回0时表示成功 * 否则, 表示出现了错误 */int oss_media_hls_stream_write(uint8_t *video_buf, uint64_t video_len, uint8_t *audio_buf, uint64_t audio_len, oss_media_hls_stream_t *stream); 示例程序: static void write_video_audio_vod() { int ret; int max_size = 10 * 1024 * 1024; FILE *h264_file, *aac_file; uint8_t *h264_buf, *aac_buf; int h264_len, aac_len; oss_media_hls_stream_options_t options; oss_media_hls_stream_t *stream; /* 设置HLS stream的参数值 */ options.is_live = 0; options.bucket_name = "<your buckete name>"; options.ts_name_prefix = "vod/video_audio/test"; options.m3u8_name = "vod/video_audio/vod.m3u8"; options.video_frame_rate = 30; options.audio_sample_rate = 24000; options.hls_time = 5; /* 打开HLS stream */ stream = oss_media_hls_stream_open(auth_func, &options); if (stream == NULL) { printf("open hls stream failed.\n"); return; } /* 创建两个buffer用来存储音频和视频数据 */ h264_buf = malloc(max_size); aac_buf = malloc(max_size); /* 读取一段视频数据和音频数据,然后调用接口写入OSS */ { h264_file = fopen("/path/to/video/1.h264", "r"); h264_len = fread(h264_buf, 1, max_size, h264_file); fclose(h264_file); aac_file = fopen("/path/to/audio/1.aac", "r"); aac_len = fread(aac_buf, 1, max_size, aac_file); fclose(aac_file); ret = oss_media_hls_stream_write(h264_buf, h264_len, aac_buf, aac_len, stream); if (ret != 0) { printf("write vod stream failed.\n"); return; } } /* 再读取一段视频数据和音频数据,然后调用接口写入OSS */ { h264_file = fopen("/path/to/video/2.h264", "r"); h264_len = fread(h264_buf, 1, max_size, h264_file); fclose(h264_file); aac_file = fopen("/path/to/audio/1.aac", "r"); aac_len = fread(aac_buf, 1, max_size, aac_file); fclose(aac_file); ret = oss_media_hls_stream_write(h264_buf, h264_len, aac_buf, aac_len, stream); if (ret != 0) { printf("write vod stream failed.\n"); return; } } /* 写完数据后,关闭HLS stream */ ret = oss_media_hls_stream_close(stream); if (ret != 0) { printf("close vod stream failed.\n"); return; } /* 释放资源 */ free(h264_buf); free(aac_buf); printf("convert H.264 and aac to HLS vod succeeded\n");} 注: 目前的录播、直播接口都支持只有视频,只有音频,同时有音视频等。示例代码参考:GitHub目前的录播、直播接口比较初级,用户如果有高级需求,可以模拟这两个接口,使用基础接口自助实现高级定制功能。可以通过示例程序观看效果

2019-12-01 23:15:00 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档OSS MEDIA C SDK 客户端部分支持将接收到的H.264、AAC封装为TS、M3U8格式后写入OSS,除了基础接口外,还提供封装好的录播、直播接口。 接口HLS相关封装接口都位于oss_media_hls_stream.h中,目前提供的接口有: oss_media_hls_stream_openoss_media_hls_stream_writeoss_media_hls_stream_close 下面详细介绍各个接口的功能和注意事项 基础结构体介绍/** * OSS MEDIA HLS STREAM OPTIONS的描述信息 */typedef struct oss_media_hls_stream_options_s { int8_t is_live; char *bucket_name; char *ts_name_prefix; char *m3u8_name; int32_t video_frame_rate; int32_t audio_sample_rate; int32_t hls_time; int32_t hls_list_size;} oss_media_hls_stream_options_t;/** * OSS MEDIA HLS STREAM的描述信息 */typedef struct oss_media_hls_stream_s { const oss_media_hls_stream_options_t *options; oss_media_hls_file_t *ts_file; oss_media_hls_file_t *m3u8_file; oss_media_hls_frame_t *video_frame; oss_media_hls_frame_t *audio_frame; oss_media_hls_m3u8_info_t *m3u8_infos; int32_t ts_file_index; int64_t current_file_begin_pts; int32_t has_aud; aos_pool_t *pool;} oss_media_hls_stream_t; 注: is_live,是否是直播模式,直播模式的时候M3U8文件里面只最新的几个ts文件信息bucket_name,存储HLS文件的存储空间名称ts_name_prefix,TS文件名称的前缀m3u8_name,M3U8文件名称video_frame_rate,视频数据的帧率audio_sample_rate,音频数据的采样率hls_time,每个ts文件最大持续时间hls_list_size,直播模式时在M3U8文件中最多保留的ts文件个数 打开HLS stream文件/** * @brief 打开一个oss hls文件 * @param[in] auth_func 授权函数,设置access_key_id/access_key_secret等 * @param[in] options 配置信息 * @return: * 返回非NULL时成功,否则失败 */oss_media_hls_stream_t* oss_media_hls_stream_open(auth_fn_t auth_func, const oss_media_hls_stream_options_t *options); 注: 示例代码参考:GitHub 关闭HLS stream文件/** * @brief 关闭HLS stream文件 */int oss_media_hls_stream_close(oss_media_hls_stream_t *stream); 注: 示例代码参考:GitHub 写HLS stream文件/** * @brief 写入视频和音频数据 * @param[in] video_buf 视频数据 * @param[in] video_len 视频数据的长度,可以为0 * @param[in] audio_buf 音频数据 * @param[in] audio_len 音频数据的长度,可以为0 * @param[in] stream HLS stream * @return: * 返回0时表示成功 * 否则, 表示出现了错误 */int oss_media_hls_stream_write(uint8_t *video_buf, uint64_t video_len, uint8_t *audio_buf, uint64_t audio_len, oss_media_hls_stream_t *stream); 示例程序: static void write_video_audio_vod() { int ret; int max_size = 10 * 1024 * 1024; FILE *h264_file, *aac_file; uint8_t *h264_buf, *aac_buf; int h264_len, aac_len; oss_media_hls_stream_options_t options; oss_media_hls_stream_t *stream; /* 设置HLS stream的参数值 */ options.is_live = 0; options.bucket_name = "<your buckete name>"; options.ts_name_prefix = "vod/video_audio/test"; options.m3u8_name = "vod/video_audio/vod.m3u8"; options.video_frame_rate = 30; options.audio_sample_rate = 24000; options.hls_time = 5; /* 打开HLS stream */ stream = oss_media_hls_stream_open(auth_func, &options); if (stream == NULL) { printf("open hls stream failed.\n"); return; } /* 创建两个buffer用来存储音频和视频数据 */ h264_buf = malloc(max_size); aac_buf = malloc(max_size); /* 读取一段视频数据和音频数据,然后调用接口写入OSS */ { h264_file = fopen("/path/to/video/1.h264", "r"); h264_len = fread(h264_buf, 1, max_size, h264_file); fclose(h264_file); aac_file = fopen("/path/to/audio/1.aac", "r"); aac_len = fread(aac_buf, 1, max_size, aac_file); fclose(aac_file); ret = oss_media_hls_stream_write(h264_buf, h264_len, aac_buf, aac_len, stream); if (ret != 0) { printf("write vod stream failed.\n"); return; } } /* 再读取一段视频数据和音频数据,然后调用接口写入OSS */ { h264_file = fopen("/path/to/video/2.h264", "r"); h264_len = fread(h264_buf, 1, max_size, h264_file); fclose(h264_file); aac_file = fopen("/path/to/audio/1.aac", "r"); aac_len = fread(aac_buf, 1, max_size, aac_file); fclose(aac_file); ret = oss_media_hls_stream_write(h264_buf, h264_len, aac_buf, aac_len, stream); if (ret != 0) { printf("write vod stream failed.\n"); return; } } /* 写完数据后,关闭HLS stream */ ret = oss_media_hls_stream_close(stream); if (ret != 0) { printf("close vod stream failed.\n"); return; } /* 释放资源 */ free(h264_buf); free(aac_buf); printf("convert H.264 and aac to HLS vod succeeded\n");} 注: 目前的录播、直播接口都支持只有视频,只有音频,同时有音视频等。示例代码参考:GitHub目前的录播、直播接口比较初级,用户如果有高级需求,可以模拟这两个接口,使用基础接口自助实现高级定制功能。可以通过示例程序观看效果

2019-12-01 23:15:01 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档OSS MEDIA C SDK 客户端部分支持将接收到的H.264、AAC封装为TS、M3U8格式后写入OSS,除了基础接口外,还提供封装好的录播、直播接口。 接口HLS相关封装接口都位于oss_media_hls_stream.h中,目前提供的接口有: oss_media_hls_stream_openoss_media_hls_stream_writeoss_media_hls_stream_close 下面详细介绍各个接口的功能和注意事项 基础结构体介绍/** * OSS MEDIA HLS STREAM OPTIONS的描述信息 */typedef struct oss_media_hls_stream_options_s { int8_t is_live; char *bucket_name; char *ts_name_prefix; char *m3u8_name; int32_t video_frame_rate; int32_t audio_sample_rate; int32_t hls_time; int32_t hls_list_size;} oss_media_hls_stream_options_t;/** * OSS MEDIA HLS STREAM的描述信息 */typedef struct oss_media_hls_stream_s { const oss_media_hls_stream_options_t *options; oss_media_hls_file_t *ts_file; oss_media_hls_file_t *m3u8_file; oss_media_hls_frame_t *video_frame; oss_media_hls_frame_t *audio_frame; oss_media_hls_m3u8_info_t *m3u8_infos; int32_t ts_file_index; int64_t current_file_begin_pts; int32_t has_aud; aos_pool_t *pool;} oss_media_hls_stream_t; 注: is_live,是否是直播模式,直播模式的时候M3U8文件里面只最新的几个ts文件信息bucket_name,存储HLS文件的存储空间名称ts_name_prefix,TS文件名称的前缀m3u8_name,M3U8文件名称video_frame_rate,视频数据的帧率audio_sample_rate,音频数据的采样率hls_time,每个ts文件最大持续时间hls_list_size,直播模式时在M3U8文件中最多保留的ts文件个数 打开HLS stream文件/** * @brief 打开一个oss hls文件 * @param[in] auth_func 授权函数,设置access_key_id/access_key_secret等 * @param[in] options 配置信息 * @return: * 返回非NULL时成功,否则失败 */oss_media_hls_stream_t* oss_media_hls_stream_open(auth_fn_t auth_func, const oss_media_hls_stream_options_t *options); 注: 示例代码参考:GitHub 关闭HLS stream文件/** * @brief 关闭HLS stream文件 */int oss_media_hls_stream_close(oss_media_hls_stream_t *stream); 注: 示例代码参考:GitHub 写HLS stream文件/** * @brief 写入视频和音频数据 * @param[in] video_buf 视频数据 * @param[in] video_len 视频数据的长度,可以为0 * @param[in] audio_buf 音频数据 * @param[in] audio_len 音频数据的长度,可以为0 * @param[in] stream HLS stream * @return: * 返回0时表示成功 * 否则, 表示出现了错误 */int oss_media_hls_stream_write(uint8_t *video_buf, uint64_t video_len, uint8_t *audio_buf, uint64_t audio_len, oss_media_hls_stream_t *stream); 示例程序: static void write_video_audio_vod() { int ret; int max_size = 10 * 1024 * 1024; FILE *h264_file, *aac_file; uint8_t *h264_buf, *aac_buf; int h264_len, aac_len; oss_media_hls_stream_options_t options; oss_media_hls_stream_t *stream; /* 设置HLS stream的参数值 */ options.is_live = 0; options.bucket_name = "<your buckete name>"; options.ts_name_prefix = "vod/video_audio/test"; options.m3u8_name = "vod/video_audio/vod.m3u8"; options.video_frame_rate = 30; options.audio_sample_rate = 24000; options.hls_time = 5; /* 打开HLS stream */ stream = oss_media_hls_stream_open(auth_func, &options); if (stream == NULL) { printf("open hls stream failed.\n"); return; } /* 创建两个buffer用来存储音频和视频数据 */ h264_buf = malloc(max_size); aac_buf = malloc(max_size); /* 读取一段视频数据和音频数据,然后调用接口写入OSS */ { h264_file = fopen("/path/to/video/1.h264", "r"); h264_len = fread(h264_buf, 1, max_size, h264_file); fclose(h264_file); aac_file = fopen("/path/to/audio/1.aac", "r"); aac_len = fread(aac_buf, 1, max_size, aac_file); fclose(aac_file); ret = oss_media_hls_stream_write(h264_buf, h264_len, aac_buf, aac_len, stream); if (ret != 0) { printf("write vod stream failed.\n"); return; } } /* 再读取一段视频数据和音频数据,然后调用接口写入OSS */ { h264_file = fopen("/path/to/video/2.h264", "r"); h264_len = fread(h264_buf, 1, max_size, h264_file); fclose(h264_file); aac_file = fopen("/path/to/audio/1.aac", "r"); aac_len = fread(aac_buf, 1, max_size, aac_file); fclose(aac_file); ret = oss_media_hls_stream_write(h264_buf, h264_len, aac_buf, aac_len, stream); if (ret != 0) { printf("write vod stream failed.\n"); return; } } /* 写完数据后,关闭HLS stream */ ret = oss_media_hls_stream_close(stream); if (ret != 0) { printf("close vod stream failed.\n"); return; } /* 释放资源 */ free(h264_buf); free(aac_buf); printf("convert H.264 and aac to HLS vod succeeded\n");} 注: 目前的录播、直播接口都支持只有视频,只有音频,同时有音视频等。示例代码参考:GitHub目前的录播、直播接口比较初级,用户如果有高级需求,可以模拟这两个接口,使用基础接口自助实现高级定制功能。可以通过示例程序观看效果

2019-12-01 23:15:01 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档OSS MEDIA C SDK 客户端部分支持将接收到的H.264、AAC封装为TS、M3U8格式后写入OSS,除了基础接口外,还提供封装好的录播、直播接口。 接口HLS相关封装接口都位于oss_media_hls_stream.h中,目前提供的接口有: oss_media_hls_stream_openoss_media_hls_stream_writeoss_media_hls_stream_close 下面详细介绍各个接口的功能和注意事项 基础结构体介绍/** * OSS MEDIA HLS STREAM OPTIONS的描述信息 */typedef struct oss_media_hls_stream_options_s { int8_t is_live; char *bucket_name; char *ts_name_prefix; char *m3u8_name; int32_t video_frame_rate; int32_t audio_sample_rate; int32_t hls_time; int32_t hls_list_size;} oss_media_hls_stream_options_t;/** * OSS MEDIA HLS STREAM的描述信息 */typedef struct oss_media_hls_stream_s { const oss_media_hls_stream_options_t *options; oss_media_hls_file_t *ts_file; oss_media_hls_file_t *m3u8_file; oss_media_hls_frame_t *video_frame; oss_media_hls_frame_t *audio_frame; oss_media_hls_m3u8_info_t *m3u8_infos; int32_t ts_file_index; int64_t current_file_begin_pts; int32_t has_aud; aos_pool_t *pool;} oss_media_hls_stream_t; 注: is_live,是否是直播模式,直播模式的时候M3U8文件里面只最新的几个ts文件信息bucket_name,存储HLS文件的存储空间名称ts_name_prefix,TS文件名称的前缀m3u8_name,M3U8文件名称video_frame_rate,视频数据的帧率audio_sample_rate,音频数据的采样率hls_time,每个ts文件最大持续时间hls_list_size,直播模式时在M3U8文件中最多保留的ts文件个数 打开HLS stream文件/** * @brief 打开一个oss hls文件 * @param[in] auth_func 授权函数,设置access_key_id/access_key_secret等 * @param[in] options 配置信息 * @return: * 返回非NULL时成功,否则失败 */oss_media_hls_stream_t* oss_media_hls_stream_open(auth_fn_t auth_func, const oss_media_hls_stream_options_t *options); 注: 示例代码参考:GitHub 关闭HLS stream文件/** * @brief 关闭HLS stream文件 */int oss_media_hls_stream_close(oss_media_hls_stream_t *stream); 注: 示例代码参考:GitHub 写HLS stream文件/** * @brief 写入视频和音频数据 * @param[in] video_buf 视频数据 * @param[in] video_len 视频数据的长度,可以为0 * @param[in] audio_buf 音频数据 * @param[in] audio_len 音频数据的长度,可以为0 * @param[in] stream HLS stream * @return: * 返回0时表示成功 * 否则, 表示出现了错误 */int oss_media_hls_stream_write(uint8_t *video_buf, uint64_t video_len, uint8_t *audio_buf, uint64_t audio_len, oss_media_hls_stream_t *stream); 示例程序: static void write_video_audio_vod() { int ret; int max_size = 10 * 1024 * 1024; FILE *h264_file, *aac_file; uint8_t *h264_buf, *aac_buf; int h264_len, aac_len; oss_media_hls_stream_options_t options; oss_media_hls_stream_t *stream; /* 设置HLS stream的参数值 */ options.is_live = 0; options.bucket_name = "<your buckete name>"; options.ts_name_prefix = "vod/video_audio/test"; options.m3u8_name = "vod/video_audio/vod.m3u8"; options.video_frame_rate = 30; options.audio_sample_rate = 24000; options.hls_time = 5; /* 打开HLS stream */ stream = oss_media_hls_stream_open(auth_func, &options); if (stream == NULL) { printf("open hls stream failed.\n"); return; } /* 创建两个buffer用来存储音频和视频数据 */ h264_buf = malloc(max_size); aac_buf = malloc(max_size); /* 读取一段视频数据和音频数据,然后调用接口写入OSS */ { h264_file = fopen("/path/to/video/1.h264", "r"); h264_len = fread(h264_buf, 1, max_size, h264_file); fclose(h264_file); aac_file = fopen("/path/to/audio/1.aac", "r"); aac_len = fread(aac_buf, 1, max_size, aac_file); fclose(aac_file); ret = oss_media_hls_stream_write(h264_buf, h264_len, aac_buf, aac_len, stream); if (ret != 0) { printf("write vod stream failed.\n"); return; } } /* 再读取一段视频数据和音频数据,然后调用接口写入OSS */ { h264_file = fopen("/path/to/video/2.h264", "r"); h264_len = fread(h264_buf, 1, max_size, h264_file); fclose(h264_file); aac_file = fopen("/path/to/audio/1.aac", "r"); aac_len = fread(aac_buf, 1, max_size, aac_file); fclose(aac_file); ret = oss_media_hls_stream_write(h264_buf, h264_len, aac_buf, aac_len, stream); if (ret != 0) { printf("write vod stream failed.\n"); return; } } /* 写完数据后,关闭HLS stream */ ret = oss_media_hls_stream_close(stream); if (ret != 0) { printf("close vod stream failed.\n"); return; } /* 释放资源 */ free(h264_buf); free(aac_buf); printf("convert H.264 and aac to HLS vod succeeded\n");} 注: 目前的录播、直播接口都支持只有视频,只有音频,同时有音视频等。示例代码参考:GitHub目前的录播、直播接口比较初级,用户如果有高级需求,可以模拟这两个接口,使用基础接口自助实现高级定制功能。可以通过示例程序观看效果

2019-12-01 23:15:01 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档OSS MEDIA C SDK 客户端部分支持将接收到的H.264、AAC封装为TS、M3U8格式后写入OSS,除了基础接口外,还提供封装好的录播、直播接口。 接口HLS相关封装接口都位于oss_media_hls_stream.h中,目前提供的接口有: oss_media_hls_stream_openoss_media_hls_stream_writeoss_media_hls_stream_close 下面详细介绍各个接口的功能和注意事项 基础结构体介绍/** * OSS MEDIA HLS STREAM OPTIONS的描述信息 */typedef struct oss_media_hls_stream_options_s { int8_t is_live; char *bucket_name; char *ts_name_prefix; char *m3u8_name; int32_t video_frame_rate; int32_t audio_sample_rate; int32_t hls_time; int32_t hls_list_size;} oss_media_hls_stream_options_t;/** * OSS MEDIA HLS STREAM的描述信息 */typedef struct oss_media_hls_stream_s { const oss_media_hls_stream_options_t *options; oss_media_hls_file_t *ts_file; oss_media_hls_file_t *m3u8_file; oss_media_hls_frame_t *video_frame; oss_media_hls_frame_t *audio_frame; oss_media_hls_m3u8_info_t *m3u8_infos; int32_t ts_file_index; int64_t current_file_begin_pts; int32_t has_aud; aos_pool_t *pool;} oss_media_hls_stream_t; 注: is_live,是否是直播模式,直播模式的时候M3U8文件里面只最新的几个ts文件信息bucket_name,存储HLS文件的存储空间名称ts_name_prefix,TS文件名称的前缀m3u8_name,M3U8文件名称video_frame_rate,视频数据的帧率audio_sample_rate,音频数据的采样率hls_time,每个ts文件最大持续时间hls_list_size,直播模式时在M3U8文件中最多保留的ts文件个数 打开HLS stream文件/** * @brief 打开一个oss hls文件 * @param[in] auth_func 授权函数,设置access_key_id/access_key_secret等 * @param[in] options 配置信息 * @return: * 返回非NULL时成功,否则失败 */oss_media_hls_stream_t* oss_media_hls_stream_open(auth_fn_t auth_func, const oss_media_hls_stream_options_t *options); 注: 示例代码参考:GitHub 关闭HLS stream文件/** * @brief 关闭HLS stream文件 */int oss_media_hls_stream_close(oss_media_hls_stream_t *stream); 注: 示例代码参考:GitHub 写HLS stream文件/** * @brief 写入视频和音频数据 * @param[in] video_buf 视频数据 * @param[in] video_len 视频数据的长度,可以为0 * @param[in] audio_buf 音频数据 * @param[in] audio_len 音频数据的长度,可以为0 * @param[in] stream HLS stream * @return: * 返回0时表示成功 * 否则, 表示出现了错误 */int oss_media_hls_stream_write(uint8_t *video_buf, uint64_t video_len, uint8_t *audio_buf, uint64_t audio_len, oss_media_hls_stream_t *stream); 示例程序: static void write_video_audio_vod() { int ret; int max_size = 10 * 1024 * 1024; FILE *h264_file, *aac_file; uint8_t *h264_buf, *aac_buf; int h264_len, aac_len; oss_media_hls_stream_options_t options; oss_media_hls_stream_t *stream; /* 设置HLS stream的参数值 */ options.is_live = 0; options.bucket_name = "<your buckete name>"; options.ts_name_prefix = "vod/video_audio/test"; options.m3u8_name = "vod/video_audio/vod.m3u8"; options.video_frame_rate = 30; options.audio_sample_rate = 24000; options.hls_time = 5; /* 打开HLS stream */ stream = oss_media_hls_stream_open(auth_func, &options); if (stream == NULL) { printf("open hls stream failed.\n"); return; } /* 创建两个buffer用来存储音频和视频数据 */ h264_buf = malloc(max_size); aac_buf = malloc(max_size); /* 读取一段视频数据和音频数据,然后调用接口写入OSS */ { h264_file = fopen("/path/to/video/1.h264", "r"); h264_len = fread(h264_buf, 1, max_size, h264_file); fclose(h264_file); aac_file = fopen("/path/to/audio/1.aac", "r"); aac_len = fread(aac_buf, 1, max_size, aac_file); fclose(aac_file); ret = oss_media_hls_stream_write(h264_buf, h264_len, aac_buf, aac_len, stream); if (ret != 0) { printf("write vod stream failed.\n"); return; } } /* 再读取一段视频数据和音频数据,然后调用接口写入OSS */ { h264_file = fopen("/path/to/video/2.h264", "r"); h264_len = fread(h264_buf, 1, max_size, h264_file); fclose(h264_file); aac_file = fopen("/path/to/audio/1.aac", "r"); aac_len = fread(aac_buf, 1, max_size, aac_file); fclose(aac_file); ret = oss_media_hls_stream_write(h264_buf, h264_len, aac_buf, aac_len, stream); if (ret != 0) { printf("write vod stream failed.\n"); return; } } /* 写完数据后,关闭HLS stream */ ret = oss_media_hls_stream_close(stream); if (ret != 0) { printf("close vod stream failed.\n"); return; } /* 释放资源 */ free(h264_buf); free(aac_buf); printf("convert H.264 and aac to HLS vod succeeded\n");} 注: 目前的录播、直播接口都支持只有视频,只有音频,同时有音视频等。示例代码参考:GitHub目前的录播、直播接口比较初级,用户如果有高级需求,可以模拟这两个接口,使用基础接口自助实现高级定制功能。可以通过示例程序观看效果

2019-12-01 23:15:01 0 浏览量 回答数 0

回答

可以直接作用于for循环的对象统称为可迭代对象(Iterable)。 可以被next()函数调用并不断返回下一个值的对象称为迭代器(Iterator)。 所有的Iterable均可以通过内置函数iter()来转变为Iterator。 对迭代器来讲,有一个__next()就够了。在你使用for 和 in 语句时,程序就会自动调用即将被处理的对象的迭代器对象,然后使用它的next__()方法,直到监测到一个StopIteration异常。 Python L = [1,2,3][x**2 for x in L][1, 4, 9]next(L) Traceback (most recent call last): File "", line 1, in TypeError: 'list' object is not an iterator I=iter(L)next(I) 1 next(I) 2 next(I) 3 next(I) Traceback (most recent call last): File "", line 1, in StopIteration123456789101112131415161718 L = [1,2,3][x**2 for x in L] [1, 4, 9] next(L) Traceback (most recent call last): File "", line 1, in TypeError: 'list' object is not an iterator I=iter(L)next(I) 1 next(I) 2 next(I) 3 next(I) Traceback (most recent call last): File "", line 1, in StopIteration上面例子中,列表L可以被for进行循环但是不能被内置函数next()用来查找下一个值,所以L是Iterable。 L通过iter进行包装后设为I,I可以被next()用来查找下一个值,所以I是Iterator。 题外话: 内置函数iter()仅仅是调用了对象的__iter()方法,所以list对象内部一定存在方法iter__()内置函数next()仅仅是调用了对象的__next()方法,所以list对象内部一定不存在方法next__(),但是Itrator中一定存在这个方法。for循环内部事实上就是先调用iter()把Iterable变成Iterator在进行循环迭代的。Python L = [4,5,6]I = L.__iter__()L.__next__() Traceback (most recent call last): File "", line 1, in AttributeError: 'list' object has no attribute '__next__' I.__next__() 4 from collections import Iterator, Iterableisinstance(L, Iterable) True isinstance(L, Iterator) False isinstance(I, Iterable) True isinstance(I, Iterator) True [x**2 for x in I] [25, 36]12345678910111213141516171819 L = [4,5,6]I = L.__iter__()L.__next__() Traceback (most recent call last): File "", line 1, in AttributeError: 'list' object has no attribute '__next__' I.__next__() 4 from collections import Iterator, Iterableisinstance(L, Iterable) True isinstance(L, Iterator) False isinstance(I, Iterable) True isinstance(I, Iterator) True [x**2 for x in I] [25, 36]4.Iterator继承自Iterable,从下面的测试中可以很方便的看到Iterator包含__iter()和next()方法,而Iteratble仅仅包含iter__()。 Python from collections import Iterator, Iterablehelp(Iterator) Help on class Iterator: class Iterator(Iterable) | Method resolution order: | Iterator | Iterable | builtins.object |**注解:从这里可以看出Iterable继承自object, Iterator继承自Iterable。 | Methods defined here: | | __iter__(self) | | __next__(self) | Return the next item from the iterator. When exhausted, raise StopIteration...... help(Iterable) Help on class Iterable: class Iterable(builtins.object) | Methods defined here: | | __iter__(self)......12345678910111213141516171819202122232425 from collections import Iterator, Iterablehelp(Iterator) Help on class Iterator: class Iterator(Iterable) | Method resolution order: | Iterator | Iterable | builtins.object |**注解:从这里可以看出Iterable继承自object, Iterator继承自Iterable。 | Methods defined here: | | __iter__(self) | | __next__(self) | Return the next item from the iterator. When exhausted, raise StopIteration...... help(Iterable) Help on class Iterable: class Iterable(builtins.object) | Methods defined here: | | __iter__(self)...... iterable需要包含有__iter()方法用来返回iterator,而iterator需要包含有next__()方法用来被循环 如果我们自己定义迭代器,只要在类里面定义一个 iter() 函数,用它来返回一个带 next() 方法的对象就够了。 直接上代码 Python class Iterable: def __iter__(self): return Iterator() class Iterator: def __init__(self): self.start=-1 def __next__(self): self.start +=2 if self.start >10: raise StopIteration return self.start I = Iterable()for i in I: print(i) 12345678910111213141516class Iterable: def __iter__(self): return Iterator() class Iterator: def __init__(self): self.start=-1 def __next__(self): self.start +=2 if self.start >10: raise StopIteration return self.start I = Iterable()for i in I: print(i) 上面的代码实现的是找到10以内的奇数,代码中的类名可以随便取,不是一定需要使用我上面提供的类名的。 如果在Iterator的__next__方法中没有实现StopIteration异常,那么则是表示的全部奇数,那么需要在调用的时候设置退出循环的条件。 Python class Iterable: def __iter__(self): return Iterator() class Iterator: def __init__(self): self.start=-1 def __next__(self): self.start +=2 return self.start I = Iterable()for count, i in zip(range(5),I): #也可以用内置函数enumerate来实现计数工作。 print(i) 1234567891011121314class Iterable: def __iter__(self): return Iterator() class Iterator: def __init__(self): self.start=-1 def __next__(self): self.start +=2 return self.start I = Iterable()for count, i in zip(range(5),I): #也可以用内置函数enumerate来实现计数工作。 print(i) 我们通过range来实现打印多少个元素,这里表示打印5个元素,返回结果和上面一致。 当然,我们可以把这两个类合并在一起,这样实现程序的简练。最终版本如下 Python class Iterable: def __iter__(self): return self def __init__(self): self.start=-1 def __next__(self): self.start +=2 if self.start >10: raise StopIteration return self.start I = Iterable()for i in I: print(i) 1234567891011121314class Iterable: def __iter__(self): return self def __init__(self): self.start=-1 def __next__(self): self.start +=2 if self.start >10: raise StopIteration return self.start I = Iterable()for i in I: print(i) 复制迭代器 迭代器是一次性消耗品,使用完了以后就空了,请看。 Python L=[1,2,3]I=iter(L)for i in I: ... print(i, end='-')...1-2-3- next(I) Traceback (most recent call last): File "", line 1, in StopIteration12345678910 L=[1,2,3]I=iter(L)for i in I: ... print(i, end='-')...1-2-3- next(I) Traceback (most recent call last): File "", line 1, in StopIteration当循环以后就殆尽了,再次使用调用时会引发StopIteration异常。 我们想通过直接赋值的形式把迭代器保存起来,可以下次使用。但是通过下面的范例可以看出来,根本不管用。 Python I=iter(L)J=Inext(I) 1 next(J) 2 next(I) 3 next(J) Traceback (most recent call last): File "", line 1, in StopIteration123456789101112 I=iter(L)J=Inext(I) 1 next(J) 2 next(I) 3 next(J) Traceback (most recent call last): File "", line 1, in StopIteration那怎么样才能达到我们要的效果呢? 我们需要使用copy包中的deepcopy了,请看下面: Python import copyI=iter(L)J=copy.deepcopy(I)next(I) 1 next(I) 2 next(J) 1123456789 import copyI=iter(L)J=copy.deepcopy(I)next(I) 1 next(I) 2 next(J) 1补充:迭代器不能向后移动, 不能回到开始。 所以需要做一些特殊的事情才能实现向后移动等功能。 以上代码均在Python 3.4 中测试通过。 日志: 8月13日完成8月14日添加关于Iterator, Iterable的更多解释在题外话的第4点。

xuning715 2019-12-02 01:10:08 0 浏览量 回答数 0

问题

Media-C-SDK之如何实现客户端?

青衫无名 2019-12-01 21:47:37 1345 浏览量 回答数 0

问题

检索两个独立文件夹(目录)中的文件列表。我如何得到什么打印在终端打印到一个新的文本文件?

kun坤 2019-12-27 10:27:04 0 浏览量 回答数 1

回答

is_file() 函数检查指定的文件名是否是正常的文件。is_file(file)file:规定要检查的文件。如果文件存在且为正常的文件,则返回 true。$result = is_file('./Upload/header.jpg); if($result){ .... }

小旋风柴进 2019-12-02 02:03:12 0 浏览量 回答数 0

问题

PHP单文件加载的性能的问题:报错

kun坤 2020-06-07 14:40:18 0 浏览量 回答数 1

问题

找不到ipynb中view_sentence_range()函数的来源

一码平川MACHEL 2019-12-01 19:31:30 490 浏览量 回答数 1

问题

在自定义Python类中动态地重新分配

kun坤 2019-12-28 13:56:10 0 浏览量 回答数 1

回答

两个方法的应用场景还是有所区别的。register_shutdown_function功能:注册一个方法,当一个请求request执行完毕时,调用这个注册的方法。注意,哪怕在执行过程中发生error导致本次请求被强制退出,注册的方法也会执行。应用场景一:function catch_error(){ $error = error_get_last(); if($error){ var_dump($error); } } register_shutdown_function(&amp;quot;catch_error&amp;quot;); ini_set('memory_limit','1M'); $content = str_repeat(&amp;quot;aaaaaaaaaaaaaaaaaaaaaaa&amp;quot;,100000); echo &amp;quot;aa&amp;quot;;输出信息大概如下:array(4) { [&quot;type&quot;]=&gt; int(1) [&quot;message&quot;]=&gt; string(80) “Allowed memory size of 1048576 bytes exhausted (tried to allocate 2300001 bytes)” [&quot;file&quot;]=&gt; string(39) “/test.php” [&quot;line&quot;]=&gt; int(13) }可见,上面的代码正常的捕捉了内存不足的错误。应用场景二检查请求是否正常结束。示例代码如下:function monitor(){ global $is_end; if($is_end == true){ echo &amp;quot;success&amp;quot;; }else{ echo &amp;quot;fail&amp;quot;; } } register_shutdown_function(&amp;quot;monitor&amp;quot;); $is_end = false; die(); $is_end = true;页面输出结果为:fail可见,即便是调用了die函数。注册的monitor函数也正常执行了。fastcgi_finish_request功能:flush数据到客户端。调用这个方法后,再有任何输出内容,都不会输出到客户端。应用场景:如果一个请求的处理内容中,有一部分是不需要发送到客户端时,就可以先生成输出到客户端的内容,然后调用此方法。方法被调用后,内容就会输出到客户端。而不需要输出到客户端的内容,可以放在此方法后。这样可以提高响应速度。示例代码如下:echo &quot;a&quot;; fastcgi_finish_request(); echo &quot;b&quot;; file_put_contents(&quot;/tmp/test&quot;,&quot;bo56.com&quot;); die(); file_put_contents(&quot;/tmp/b56&quot;,&quot;博学无忧&quot;);页面输出结果为:a可见,fastcgi_finish_request方法后的echo “b” 并没有输出到客户端。但是你会发现在/tmp/test目录下正常的创建了文件。但是/tmp/bo56文件没创建。参考资料妙用php中的register_shutdown_function和fastcgi_finish_request

exinnet 2019-12-02 01:30:41 0 浏览量 回答数 0

回答

1.字符串转义序列转义字符 描述(在行尾时) 续行符\ 反斜杠符号' 单引号" 双引号a 响铃b 退格(Backspace)e 转义000 空n 换行v 纵向制表符t 横向制表符r 回车f 换页oyy 八进制数yy代表的字符,例如:o12代表换行xyy 十进制数yy代表的字符,例如:x0a代表换行other 其它的字符以普通格式输出 2.字符串格式化 3.操作符 一、算术运算符 注意: 双斜杠 // 除法总是向下取整。 从符点数到整数的转换可能会舍入也可能截断,建议使用math.floor()和math.ceil()明确定义的转换。 Python定义pow(0, 0)和0 ** 0等于1。 二、比较运算符 运算符 描述< 小于<= 小于或等于 大于= 大于或等于== 等于 != 不等于is 判断两个标识符是不是引用自一个对象is not 判断两个标识符是不是引用自不同对象注意: 八个比较运算符优先级相同。 Python允许x < y <= z这样的链式比较,它相当于x < y and y <= z。 复数不能进行大小比较,只能比较是否相等。 三、逻辑运算符 运算符 描述 备注x or y if x is false, then y, elsex x andy if x is false, then x, elsey not x if x is false, then True,elseFalse 注意: or是个短路运算符,它只有在第一个运算数为False时才会计算第二个运算数的值。 and也是个短路运算符,它只有在第一个运算数为True时才会计算第二个运算数的值。 not的优先级比其他类型的运算符低,所以not a == b相当于not (a == b),而 a == not b是错误的。 四、位运算符 运算符 描述 备注x | y 按位或运算符 x ^ y 按位异或运算符 x & y 按位与运算符 x << n 左移动运算符 x >> n 右移动运算符 ~x 按位取反运算符 五、赋值运算符 复合赋值运算符与算术运算符是一一对应的: 六、成员运算符 Python提供了成员运算符,测试一个元素是否在一个序列(Sequence)中。 运算符 描述in 如果在指定的序列中找到值返回True,否则返回False。not in 如果在指定的序列中没有找到值返回True,否则返回False。 4.关键字总结 Python中的关键字包括如下: and del from not while as elif global or with assert else if pass yield break except import print class exec in raise continue finally is return def for lambda try你想看看有哪些关键字?OK,打开一个终端,就像这样~ long@zhouyl:~$ pythonPython 2.7.3 (default, Jan 2 2013, 16:53:07) [GCC 4.7.2] on linux2Type "help", "copyright", "credits" or "license" for more information. import keywordkeyword.kwlist ['and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'exec', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'not', 'or', 'pass', 'print', 'raise', 'return', 'try', 'while', 'with', 'yield'] ============================== 华丽的 正文分隔符 ======================================== 看到这些关键字你还能记得多少?你不妨自己一个一个对照想想它的用法,下面是我总结的,我根据前面的学习笔记将上述关键字分为以下几类: 1.判断、循环 对于Python的循环及判断主要包括这些关键字: if elif else for while break continue and or is not in 这几个关键字在前面介绍 if 语法、while语法、for语法以及and...or语法中已有介绍,下面再一笔带过: 1.1 if 语法 if语法与C语言、shell脚本之下的非常类似,最大的区别就是冒号以及严格的缩进,当然这两点也是Python区别于其他语言的地方: if condition1: do something elif condition2: do another thing else: also do something 1.2 while 语法 Python的while语法区别于C、shell下的while除了冒号及缩进之外,还有一点就是while可以携带一个可选的else语句: while condition: do something else: do something 注:else语句是可选的,但是使用while语句时一定要注意判断语句可以跳出! 1.3 for 语法 与while类似,Python的for循环也包括一个可选的else语句(跳出for循环时执行,但是如果是从break语句跳出则不执行else语句块中的代码!),而且for 加上 关键字in就组成了最常见的列表解析用法(以后会写个专门的博客)。 下面是for的一般用法: for i in range(1,10,2): do something if condition: break else: do something for的列表解析用法: for items in list: print items 1.4 and...or 语法 Python的and/or操作与其他语言不同的是它的返回值是参与判断的两个值之一,所以我们可以通过这个特性来实现Python下的 a ? b : c ! 有C语言基础的知道 “ a ? b : c ! ” 语法是判断 a,如果正确则执行b,否则执行 c! 而Python下我们可以这么用:“ a and b or c ”(此方法中必须保证b必须是True值),python自左向右执行此句,先判断a and b :如果a是True值,a and b语句仍需要执行b,而此时b是True值!所以a and b的值是b,而此时a and b or c就变成了b or c,因b是True值,所以b or c的结果也是b;如果a是False值,a and b语句的结果就是a,此时 a and b or c就转化为a or c,因为此时a是 False值,所以不管c是True 还是Flase,a or c的结果就是c!!!捋通逻辑的话,a and b or c 是不是就是Python下的a ? b : c ! 用法? 1.5 is ,not is 和 is not 是Python下判断同一性的关键字,通常用来判断 是 True 、False或者None(Python下的NULL)! 比如 if alue is True : ... (不记得本节的童鞋罚复习:python 学习笔记 2 -- 判断语句) 2.函数、模块、类 对于Python的函数及模块主要包括这些关键字: from import as def pass lambda return class 那么你还能记得它们么?下面简单介绍一下: 2.1 模块 Python的编程通常大量使用标准库中的模块,使用方法就是使用import 、from以及as 关键字。 比如: import sys # 导入sys模块 from sys import argv # 从sys模块中导入argv ,这个在前面介绍脚本传参数时使用到 import cPickle as p # 将cPickle模块导入并在此将它简单命名为p,此后直接可以使用p替代cPickle模块原名,这个在介绍文件输入输出时的存储器中使用到 2.2 函数 Python中定义函数时使用到def关键字,如果你当前不想写入真实的函数操作,可以使用pass关键字指代不做任何操作: def JustAFunction: pass 当然,在需要给函数返回值时就用到了return关键字,这里简单提一下Python下的函数返回值可以是多个(接收返回值时用相应数量的变量接收!)! 此外Python下有个神奇的Lambda函数,它允许你定义单行的最小函数,这是从Lisp中借用来的,可以用在任何需要函数的地方。比如: g = lambda x : x*2 # 定义一个Lambda函数用来计算参数的2倍并返回! print g(2) # 使用时使用lambda函数返回的变量作为这个函数的函数名,括号中带入相应参数即可! (不记得本节的童鞋罚复习:python 学习笔记 4 -- 函数篇) 3.异常 对于Python的异常主要包括这些关键字: try except finally raise 异常这一节还是比较简单的,将可能出现的异常放在 try: 后面的语句块中,使用except关键字捕获一定的异常并在接下来的语句块中做相应操作,而finally中接的是无论出现什么异常总在执行最后做finally: 后面的语句块(比如关闭文件等必要的操作!) raise关键字是在一定的情况下引发异常,通常结合自定义的异常类型使用。 (不记得本节的童鞋罚复习:python 学习笔记 6 -- 异常处理) 4.其他 上面的三类过后,还剩下这些关键字: print del global with assert yield exec 首先print 在前面的笔记或者任何地方你都能见到,所以还是比较熟悉的,此处就不多介绍了!del 关键字在前面的笔记中已有所涉及,比如删除列表中的某项,我们使用 “ del mylist[0] ” 可能这些剩下来的关键字你比较陌生,所以下面来介绍一下: 4.1.global 关键字 当你在函数定义内声明变量的时候,它们与函数外具有相同名称的其他变量没有任何关系,即变量名称对于函数来说是 局部 的。这称为变量的 作用域 。所有变量的作用域是它们被定义的块,从它们的名称被定义的那点开始。 eg. ? 1 2 3 4 5 6 7 8 9 10 11 !/usr/bin/python Filename: func_local.py def func(x): print'x is', x x = 2 print'Changed local x to', x x = 50 func(x) print'x is still', x 运行的结果是这样的:? 1 2 3 4 $ python func_local.py x is 50 # 运行func函数时,先打印x的值,此时带的值是作为参数带入的外部定义的50,所以能正常打印 x=50 Changed local x to 2 # 在func函数中将x赋2,并打印 x is still 50 # 运行完func函数,打印x的值,此时x的值仍然是之前赋给的50,而不是func函数中修改过的2,因为在函数中修改的只是函数内的局部变量 那么为什么我们要在这提到局部变量呢?bingo,聪明的你一下就猜到这个global就是用来定义全局变量的。也就是说如果你想要为一个在函数外定义的变量赋值,那么你就得告诉Python这个变量名不是局部的,而是 全局 的。我们使用global语句完成这一功能。没有global语句,是不可能为定义在函数外的变量赋值的。eg.? 1 2 3 4 5 6 7 8 9 10 11 12 !/usr/bin/python Filename: func_global.py def func(): global x print'x is', x x = 2 print'Changed local x to', x x = 50 func() print'Value of x is', x 运行的结果是这样的:? 1 2 3 4 $ python func_global.py x is 50 Changed global x to 2 Value of x is 2 # global语句被用来声明x是全局的——因此,当我们在函数内把值赋给x的时候,这个变化也反映在我们在主块中使用x的值的时候。 你可以使用同一个global语句指定多个全局变量。例如global x, y, z。 4.2.with 关键字 有一些任务,可能事先需要设置,事后做清理工作。对于这种场景,Python的with语句提供了一种非常方便的处理方式。一个很好的例子是文件处理,你需要获取一个文件句柄,从文件中读取数据,然后关闭文件句柄。如果不用with语句,打开一个文件并读文件的代码如下:? 1 2 3 file = open("/tmp/foo.txt") data = file.read() file.close() 当然这样直接打开有两个问题:一是可能忘记关闭文件句柄;二是文件读取数据发生异常,没有进行任何处理。下面是添加上异常处理的版本:? 1 2 3 4 5 file = open("/tmp/foo.txt") try: data = file.read() finally: file.close() 虽然这段代码运行良好,但是太冗余了。这时候就是with一展身手的时候了。除了有更优雅的语法,with还可以很好的处理上下文环境产生的异常。下面是with版本的代码:? 1 2 with open("/tmp/foo.txt") as file: data = file.read() 这看起来充满魔法,但不仅仅是魔法,Python对with的处理还很聪明。基本思想是with所求值的对象必须有一个__enter__()方法,一个__exit__()方法。with语句的执行逻辑如下:紧跟with后面的语句被求值后,返回对象的__enter__()方法被调用,这个方法的返回值将被赋值给as后面的变量。当with后面的代码块全部被执行完之后,将调用前面返回对象的__exit__()方法。 下面例子可以具体说明with如何工作:? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 !/usr/bin/python with_example01.py classSample: def __enter__(self): print"In __enter__()" return"Foo" def __exit__(self, type, value, trace): print"In __exit__()" def get_sample(): returnSample() with get_sample() as sample: print"sample:", sample 运行代码,输出如下? 1 2 3 4 $python with_example01.py In __enter__() # __enter__()方法被执行 sample: Foo # __enter__()方法返回的值 - 这个例子中是"Foo",赋值给变量'sample',执行代码块,打印变量"sample"的值为"Foo" In __exit__() # __exit__()方法被调用 4.3.assert 关键字 assert语句是一种插入调试断点到程序的一种便捷的方式。assert语句用来声明某个条件是真的,当assert语句失败的时候,会引发一AssertionError,所以结合try...except我们就可以处理这样的异常。 mylist # 此时mylist是有三个元素的列表['a', 'b', 'c']assert len(mylist) is not None # 用assert判断列表不为空,正确无返回assert len(mylist) is None # 用assert判断列表为空 Traceback (most recent call last): File "", line 1, in AssertionError # 引发AssertionError异常 4.4.yield 关键字 我们先看一个示例:? 1 2 3 4 5 6 7 8 def fab(max): n, a, b = 0,0,1 whilen < max: yield b # print b a, b = b, a + b n = n + 1 ''' 使用这个函数:? 1 2 3 4 5 6 7 8 forn in fab(5): ... print n ... 1 1 2 3 5 简单地讲,yield 的作用就是把一个函数变成一个 generator(生成器),带有 yield 的函数不再是一个普通函数,Python 解释器会将其视为一个 generator,调用 fab(5) 不会执行 fab 函数,而是返回一个 iterable(可迭代的)对象!在 for 循环执行时,每次循环都会执行 fab 函数内部的代码,执行到 yield b 时,fab 函数就返回一个迭代值,下次迭代时,代码从 yield b 的下一条语句继续执行,而函数的本地变量看起来和上次中断执行前是完全一样的,于是函数继续执行,直到再次遇到 yield。也可以手动调用 fab(5) 的 next() 方法(因为 fab(5) 是一个 generator 对象,该对象具有 next() 方法),这样我们就可以更清楚地看到 fab 的执行流程:? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 f = fab(5) f.next() 1 f.next() 1 f.next() 2 f.next() 3 f.next() 5 f.next() Traceback (most recent call last): File"", line 1, in StopIteration 当函数执行结束时,generator 自动抛出 StopIteration 异常,表示迭代完成。在 for 循环里,无需处理 StopIteration 异常,循环会正常结束。 我们可以得出以下结论:一个带有 yield 的函数就是一个 generator,它和普通函数不同,生成一个 generator 看起来像函数调用,但不会执行任何函数代码,直到对其调用 next()(在 for 循环中会自动调用 next())才开始执行。虽然执行流程仍按函数的流程执行,但每执行到一个 yield 语句就会中断,并返回一个迭代值,下次执行时从 yield 的下一个语句继续执行。看起来就好像一个函数在正常执行的过程中被 yield 中断了数次,每次中断都会通过 yield 返回当前的迭代值。 yield 的好处是显而易见的,把一个函数改写为一个 generator 就获得了迭代能力,比起用类的实例保存状态来计算下一个 next() 的值,不仅代码简洁,而且执行流程异常清晰。 注:如果看完此段你还未明白yield,没问题,因为yield是初学者的一个难点,那么你下一步需要做的就是……看一看下面参考资料中给的关于yield的博文! 4.5.exec 关键字 官方文档对于exec的解释: "This statement supports dynamic execution of Python code."也就是说使用exec可以动态执行Python代码(也可以是文件)。? 1 2 3 4 5 6 7 8 9 10 11 12 13 longer = "print "Hello World ,my name is longer"" # 比如说我们定义了一个字符串 longer 'print "Hello World ,my name is longer"' exec(longer) # 使用exec 动态执行字符串中的代码 Hello World ,my name is longer exec(sayhi) # 使用exec直接打开文件名(指定sayhi,sayhi.py以及"sayhi.py"都会报一定的错,但是我觉得直接带sayhi报错非常典型) Traceback (most recent call last): File"", line 1, in TypeError: exec: arg 1must be a string, file, or code object # python IDE报错,提示exec的第一个参 数必须是一个字符串、文件或者一个代码对象 f = file("sayhi.py") # 使用file打开sayhi.py并创建f实例 exec(f) # 使用exec直接运行文件描述符f,运行正常!! Hi,thisis [''] script 上述给的例子比较简单,注意例子中exec语句的用法和eval_r(), execfile()是不一样的. exec是一个关键字(要不然我怎么会在这里介绍呢~~~), 而eval_r()和execfile()则是内建函数。更多关于exec的使用请详看引用资料或者Google之 在需要在字符中使用特殊字符时,python用反斜杠()转义字符。 原始字符串 有时我们并不想让转义字符生效,我们只想显示字符串原来的意思,这就要用r和R来定义原始字符串。如: print r’tr’ 实际输出为“tr”。 转义字符 描述 (在行尾时) 续行符 反斜杠符号 ’ 单引号 ” 双引号 a 响铃 b 退格(Backspace) e 转义 000 空 n 换行 v 纵向制表符 t 横向制表符 r 回车 f 换页 oyy 八进制数yy代表的字符,例如:o12代表换行 xyy 十进制数yy代表的字符,例如:x0a代表换行 other 其它的字符以普通格式输出

xuning715 2019-12-02 01:10:21 0 浏览量 回答数 0

回答

Python 的 Decorator在使用上和Java/C#的Annotation很相似,就是在方法名前面加一个@XXX注解来为这个方法装饰一些东西。但是,Java/C#的Annotation也很让人望而却步,太TMD的复杂了,你要玩它,你需要了解一堆Annotation的类库文档,让人感觉就是在学另外一门语言。 而Python使用了一种相对于Decorator Pattern和Annotation来说非常优雅的方法,这种方法不需要你去掌握什么复杂的OO模型或是Annotation的各种类库规定,完全就是语言层面的玩法:一种函数式编程的技巧。如果你看过本站的《函数式编程》,你一定会为函数式编程的那种“描述你想干什么,而不是描述你要怎么去实现”的编程方式感到畅快。(如果你不了解函数式编程,那在读本文之前,还请你移步去看看《函数式编程》) 好了,我们先来点感性认识,看一个Python修饰器的Hello World的代码。 Hello World 下面是代码:文件名:hello.py def hello(fn): def wrapper(): print "hello, %s" % fn.__name__ fn() print "goodby, %s" % fn.__name__ return wrapper @hellodef foo(): print "i am foo" foo() 当你运行代码,你会看到如下输出: [chenaho@chenhao-air]$ python hello.pyhello, fooi am foogoodby, foo 你可以看到如下的东西: 1)函数foo前面有个@hello的“注解”,hello就是我们前面定义的函数hello 2)在hello函数中,其需要一个fn的参数(这就用来做回调的函数) 3)hello函数中返回了一个inner函数wrapper,这个wrapper函数回调了传进来的fn,并在回调前后加了两条语句。 Decorator 的本质 对于Python的这个@注解语法糖- Syntactic Sugar 来说,当你在用某个@decorator来修饰某个函数func时,如下所示: @decoratordef func(): pass 其解释器会解释成下面这样的语句: func = decorator(func) 尼玛,这不就是把一个函数当参数传到另一个函数中,然后再回调吗?是的,但是,我们需要注意,那里还有一个赋值语句,把decorator这个函数的返回值赋值回了原来的func。 根据《函数式编程》中的first class functions中的定义的,你可以把函数当成变量来使用,所以,decorator必需得返回了一个函数出来给func,这就是所谓的higher order function 高阶函数,不然,后面当func()调用的时候就会出错。 就我们上面那个hello.py里的例子来说, @hellodef foo(): print "i am foo" 被解释成了: foo = hello(foo) 是的,这是一条语句,而且还被执行了。你如果不信的话,你可以写这样的程序来试试看: def fuck(fn): print "fuck %s!" % fn.__name__[::-1].upper() @fuckdef wfg(): pass 没了,就上面这段代码,没有调用wfg()的语句,你会发现, fuck函数被调用了,而且还很NB地输出了我们每个人的心声! 再回到我们hello.py的那个例子,我们可以看到,hello(foo)返回了wrapper()函数,所以,foo其实变成了wrapper的一个变量,而后面的foo()执行其实变成了wrapper()。 知道这点本质,当你看到有多个decorator或是带参数的decorator,你也就不会害怕了。 比如:多个decorator @decorator_one@decorator_twodef func(): pass 相当于: func = decorator_one(decorator_two(func)) 比如:带参数的decorator: @decorator(arg1, arg2)def func(): pass 相当于: func = decorator(arg1,arg2)(func) 这意味着decorator(arg1, arg2)这个函数需要返回一个“真正的decorator”。 带参数及多个Decrorator 我们来看一个有点意义的例子:html.py def makeHtmlTag(tag, args, *kwds): def real_decorator(fn): css_class = " class='{0}'".format(kwds["css_class"]) if "css_class" in kwds else "" def wrapped(*args, **kwds): return "<"+tag+css_class+">" + fn(*args, **kwds) + "</"+tag+">" return wrapped return real_decorator @makeHtmlTag(tag="b", css_class="bold_css")@makeHtmlTag(tag="i", css_class="italic_css")def hello(): return "hello world" print hello() 输出: hello world 在上面这个例子中,我们可以看到:makeHtmlTag有两个参数。所以,为了让 hello = makeHtmlTag(arg1, arg2)(hello) 成功,makeHtmlTag 必需返回一个decorator(这就是为什么我们在makeHtmlTag中加入了real_decorator()的原因),这样一来,我们就可以进入到 decorator 的逻辑中去了—— decorator得返回一个wrapper,wrapper里回调hello。看似那个makeHtmlTag() 写得层层叠叠,但是,已经了解了本质的我们觉得写得很自然。 你看,Python的Decorator就是这么简单,没有什么复杂的东西,你也不需要了解过多的东西,使用起来就是那么自然、体贴、干爽、透气,独有的速效凹道和完美的吸收轨迹,让你再也不用为每个月的那几天感到焦虑和不安,再加上贴心的护翼设计,量多也不用当心。对不起,我调皮了。 什么,你觉得上面那个带参数的Decorator的函数嵌套太多了,你受不了。好吧,没事,我们看看下面的方法。 class式的 Decorator 首先,先得说一下,decorator的class方式,还是看个示例: class myDecorator(object): def __init__(self, fn): print "inside myDecorator.__init__()" self.fn = fn def __call__(self): self.fn() print "inside myDecorator.__call__()" @myDecoratordef aFunction(): print "inside aFunction()" print "Finished decorating aFunction()" aFunction() 输出: inside myDecorator.__init__() Finished decorating aFunction() inside aFunction() inside myDecorator.__call__() 上面这个示例展示了,用类的方式声明一个decorator。我们可以看到这个类中有两个成员:1)一个是__init__(),这个方法是在我们给某个函数decorator时被调用,所以,需要有一个fn的参数,也就是被decorator的函数。2)一个是__call__(),这个方法是在我们调用被decorator函数时被调用的。上面输出可以看到整个程序的执行顺序。 这看上去要比“函数式”的方式更易读一些。 下面,我们来看看用类的方式来重写上面的html.py的代码:html.py class makeHtmlTagClass(object): def __init__(self, tag, css_class=""): self._tag = tag self._css_class = " class='{0}'".format(css_class) if css_class !="" else "" def __call__(self, fn): def wrapped(*args, **kwargs): return "<" + self._tag + self._css_class+">" + fn(*args, **kwargs) + "</" + self._tag + ">" return wrapped @makeHtmlTagClass(tag="b", css_class="bold_css")@makeHtmlTagClass(tag="i", css_class="italic_css")def hello(name): return "Hello, {}".format(name) print hello("Hao Chen") 上面这段代码中,我们需要注意这几点:1)如果decorator有参数的话,__init__() 成员就不能传入fn了,而fn是在__call__的时候传入的。2)这段代码还展示了 wrapped(args, *kwargs) 这种方式来传递被decorator函数的参数。(其中:args是一个参数列表,kwargs是参数dict,具体的细节,请参考Python的文档或是StackOverflow的这个问题,这里就不展开了) 用Decorator设置函数的调用参数 你有三种方法可以干这个事: 第一种,通过 **kwargs,这种方法decorator会在kwargs中注入参数。 def decorate_A(function): def wrap_function(*args, **kwargs): kwargs['str'] = 'Hello!' return function(*args, **kwargs) return wrap_function @decorate_Adef print_message_A(args, *kwargs): print(kwargs['str']) print_message_A() 第二种,约定好参数,直接修改参数 def decorate_B(function): def wrap_function(*args, **kwargs): str = 'Hello!' return function(str, *args, **kwargs) return wrap_function @decorate_Bdef print_message_B(str, args, *kwargs): print(str) print_message_B() 第三种,通过 *args 注入 def decorate_C(function): def wrap_function(*args, **kwargs): str = 'Hello!' #args.insert(1, str) args = args +(str,) return function(*args, **kwargs) return wrap_function class Printer: @decorate_C def print_message(self, str, *args, **kwargs): print(str) p = Printer()p.print_message() Decorator的副作用 到这里,我相信你应该了解了整个Python的decorator的原理了。 相信你也会发现,被decorator的函数其实已经是另外一个函数了,对于最前面那个hello.py的例子来说,如果你查询一下foo.__name__的话,你会发现其输出的是“wrapper”,而不是我们期望的“foo”,这会给我们的程序埋一些坑。所以,Python的functool包中提供了一个叫wrap的decorator来消除这样的副作用。下面是我们新版本的hello.py。文件名:hello.py from functools import wrapsdef hello(fn): @wraps(fn) def wrapper(): print "hello, %s" % fn.__name__ fn() print "goodby, %s" % fn.__name__ return wrapper @hellodef foo(): '''foo help doc''' print "i am foo" pass foo()print foo.__name__ #输出 fooprint foo.__doc__ #输出 foo help doc 当然,即使是你用了functools的wraps,也不能完全消除这样的副作用。 来看下面这个示例: from inspect import getmembers, getargspecfrom functools import wraps def wraps_decorator(f): @wraps(f) def wraps_wrapper(*args, **kwargs): return f(*args, **kwargs) return wraps_wrapper class SomeClass(object): @wraps_decorator def method(self, x, y): pass obj = SomeClass()for name, func in getmembers(obj, predicate=inspect.ismethod): print "Member Name: %s" % name print "Func Name: %s" % func.func_name print "Args: %s" % getargspec(func)[0] 输出: Member Name: method Func Name: method Args: [] 你会发现,即使是你你用了functools的wraps,你在用getargspec时,参数也不见了。 要修正这一问,我们还得用Python的反射来解决,下面是相关的代码: def get_true_argspec(method): argspec = inspect.getargspec(method) args = argspec[0] if args and args[0] == 'self': return argspec if hasattr(method, '__func__'): method = method.__func__ if not hasattr(method, 'func_closure') or method.func_closure is None: raise Exception("No closure for method.") method = method.func_closure[0].cell_contents return get_true_argspec(method) 当然,我相信大多数人的程序都不会去getargspec。所以,用functools的wraps应该够用了。 一些decorator的示例 好了,现在我们来看一下各种decorator的例子: 给函数调用做缓存 这个例实在是太经典了,整个网上都用这个例子做decorator的经典范例,因为太经典了,所以,我这篇文章也不能免俗。 from functools import wrapsdef memo(fn): cache = {} miss = object() @wraps(fn) def wrapper(*args): result = cache.get(args, miss) if result is miss: result = fn(*args) cache[args] = result return result return wrapper @memodef fib(n): if n < 2: return n return fib(n - 1) + fib(n - 2) 上面这个例子中,是一个斐波拉契数例的递归算法。我们知道,这个递归是相当没有效率的,因为会重复调用。比如:我们要计算fib(5),于是其分解成fib(4) + fib(3),而fib(4)分解成fib(3)+fib(2),fib(3)又分解成fib(2)+fib(1)…… 你可看到,基本上来说,fib(3), fib(2), fib(1)在整个递归过程中被调用了两次。 而我们用decorator,在调用函数前查询一下缓存,如果没有才调用了,有了就从缓存中返回值。一下子,这个递归从二叉树式的递归成了线性的递归。 Profiler的例子 这个例子没什么高深的,就是实用一些。 import cProfile, pstats, StringIO def profiler(func): def wrapper(*args, **kwargs): datafn = func.__name__ + ".profile" # Name the data file prof = cProfile.Profile() retval = prof.runcall(func, *args, **kwargs) #prof.dump_stats(datafn) s = StringIO.StringIO() sortby = 'cumulative' ps = pstats.Stats(prof, stream=s).sort_stats(sortby) ps.print_stats() print s.getvalue() return retval return wrapper 注册回调函数 下面这个示例展示了通过URL的路由来调用相关注册的函数示例: class MyApp(): def __init__(self): self.func_map = {} def register(self, name): def func_wrapper(func): self.func_map[name] = func return func return func_wrapper def call_method(self, name=None): func = self.func_map.get(name, None) if func is None: raise Exception("No function registered against - " + str(name)) return func() app = MyApp() @app.register('/')def main_page_func(): return "This is the main page." @app.register('/next_page')def next_page_func(): return "This is the next page." print app.call_method('/')print app.call_method('/next_page') 注意:1)上面这个示例中,用类的实例来做decorator。2)decorator类中没有__call__(),但是wrapper返回了原函数。所以,原函数没有发生任何变化。 给函数打日志 下面这个示例演示了一个logger的decorator,这个decorator输出了函数名,参数,返回值,和运行时间。 from functools import wrapsdef logger(fn): @wraps(fn) def wrapper(*args, **kwargs): ts = time.time() result = fn(*args, **kwargs) te = time.time() print "function = {0}".format(fn.__name__) print " arguments = {0} {1}".format(args, kwargs) print " return = {0}".format(result) print " time = %.6f sec" % (te-ts) return result return wrapper @loggerdef multipy(x, y): return x * y @loggerdef sum_num(n): s = 0 for i in xrange(n+1): s += i return s print multipy(2, 10)print sum_num(100)print sum_num(10000000) 上面那个打日志还是有点粗糙,让我们看一个更好一点的(带log level参数的): import inspectdef get_line_number(): return inspect.currentframe().f_back.f_back.f_lineno def logger(loglevel): def log_decorator(fn): @wraps(fn) def wrapper(*args, **kwargs): ts = time.time() result = fn(*args, **kwargs) te = time.time() print "function = " + fn.__name__, print " arguments = {0} {1}".format(args, kwargs) print " return = {0}".format(result) print " time = %.6f sec" % (te-ts) if (loglevel == 'debug'): print " called_from_line : " + str(get_line_number()) return result return wrapper return log_decorator 但是,上面这个带log level参数的有两具不好的地方,1) loglevel不是debug的时候,还是要计算函数调用的时间。2) 不同level的要写在一起,不易读。 我们再接着改进: import inspect def advance_logger(loglevel): def get_line_number(): return inspect.currentframe().f_back.f_back.f_lineno def _basic_log(fn, result, *args, **kwargs): print "function = " + fn.__name__, print " arguments = {0} {1}".format(args, kwargs) print " return = {0}".format(result) def info_log_decorator(fn): @wraps(fn) def wrapper(*args, **kwargs): result = fn(*args, **kwargs) _basic_log(fn, result, args, kwargs) return wrapper def debug_log_decorator(fn): @wraps(fn) def wrapper(*args, **kwargs): ts = time.time() result = fn(*args, **kwargs) te = time.time() _basic_log(fn, result, args, kwargs) print " time = %.6f sec" % (te-ts) print " called_from_line : " + str(get_line_number()) return wrapper if loglevel is "debug": return debug_log_decorator else: return info_log_decorator 你可以看到两点,1)我们分了两个log level,一个是info的,一个是debug的,然后我们在外尾根据不同的参数返回不同的decorator。2)我们把info和debug中的相同的代码抽到了一个叫_basic_log的函数里,DRY原则。 一个MySQL的Decorator 下面这个decorator是我在工作中用到的代码,我简化了一下,把DB连接池的代码去掉了,这样能简单点,方便阅读。 import umysqlfrom functools import wraps class Configuraion: def __init__(self, env): if env == "Prod": self.host = "coolshell.cn" self.port = 3306 self.db = "coolshell" self.user = "coolshell" self.passwd = "fuckgfw" elif env == "Test": self.host = 'localhost' self.port = 3300 self.user = 'coolshell' self.db = 'coolshell' self.passwd = 'fuckgfw' def mysql(sql): _conf = Configuraion(env="Prod") def on_sql_error(err): print err sys.exit(-1) def handle_sql_result(rs): if rs.rows > 0: fieldnames = [f[0] for f in rs.fields] return [dict(zip(fieldnames, r)) for r in rs.rows] else: return [] def decorator(fn): @wraps(fn) def wrapper(*args, **kwargs): mysqlconn = umysql.Connection() mysqlconn.settimeout(5) mysqlconn.connect(_conf.host, _conf.port, _conf.user, _conf.passwd, _conf.db, True, 'utf8') try: rs = mysqlconn.query(sql, {}) except umysql.Error as e: on_sql_error(e) data = handle_sql_result(rs) kwargs["data"] = data result = fn(*args, **kwargs) mysqlconn.close() return result return wrapper return decorator @mysql(sql = "select * from coolshell" )def get_coolshell(data): ... ... ... .. 线程异步 下面量个非常简单的异步执行的decorator,注意,异步处理并不简单,下面只是一个示例。 from threading import Threadfrom functools import wraps def async(func): @wraps(func) def async_func(*args, **kwargs): func_hl = Thread(target = func, args = args, kwargs = kwargs) func_hl.start() return func_hl return async_func if name == '__main__': from time import sleep @async def print_somedata(): print 'starting print_somedata' sleep(2) print 'print_somedata: 2 sec passed' sleep(2) print 'print_somedata: 2 sec passed' sleep(2) print 'finished print_somedata' def main(): print_somedata() print 'back in main' print_somedata() print 'back in main' main() 其它 关于更多的示例,你可以参看: Python Decorator Library来源:网络

51干警网 2019-12-02 01:10:47 0 浏览量 回答数 0

问题

Python SDK示例程序

云栖大讲堂 2019-12-01 21:10:49 1466 浏览量 回答数 0

问题

Media-C-SDK之如何实现HLS封装接口?

青衫无名 2019-12-01 21:47:40 1319 浏览量 回答数 0

问题

关于Boost中has_new_operator.hpp文件的问题以及CGAL文?报错

爱吃鱼的程序员 2020-06-15 19:45:56 0 浏览量 回答数 1

问题

oss c sdk multipart上传一个文件代码参考

yjseu 2019-12-01 21:25:22 8602 浏览量 回答数 3

回答

ReOSS C/CSDK分享交流区 分块上传大文件时加入进度条,上传成功的片数,和总片数在哪个变量里面? 新手,找了注释,但是没有发现有用的信息,只知道应该在下面的代码 List Part 里修改。 s = oss_upload_part_from_file(options, &bucket, &object, &upload_id,                 part_num1, upload_file, &upload_part_resp_headers);         assert(200 == s->code);         //list part         list_part_resp_headers = aos_table_make(p, 5);         params = oss_create_list_upload_part_params(p);//所有分块信息存储在oss_list_upload_part_params_t的params中         aos_str_set(&params->part_number_marker, "");         params->max_ret = 10;         params->truncated = 0;         aos_list_init(&complete_part_list);         s = oss_list_upload_part(options, &bucket, &object, &upload_id, params, &list_part_resp_headers);//获取所有已上传的块信息         assert(200 == s->code);         assert(200 == s->code);         //通过aos_list_for_each_entry对part_list进行遍历。         aos_list_for_each_entry(oss_list_part_content_t, part_content1, &params->part_list, node){                 complete_content1 = oss_create_complete_part_content(p);                 aos_str_set(&complete_content1->part_number, part_content1->part_number.data);                 aos_str_set(&complete_content1->etag, part_content1->etag.data);                 aos_list_add_tail(&complete_content1->node, &complete_part_list);         } ------------------------- 回 77楼yjseu的帖子 谢谢您的回复! 您的说的这些条件里,现在就是不知道“累计上传的变量”在哪里。 文件的multipart上传,就在下面的这个函数中,什么时候上传完了,才能往下执行。 s = oss_upload_part_from_file(options, &bucket, &object, &upload_id,                 part_num1, upload_file, &upload_part_resp_headers); 我想的是另开一个线程,定时读取其中的一个参数中的“累计上传”,来完成进度条。 我猜测着是不是 oss_upload_file_t *upload_file 里面的file_last 是不是我想要的东西呢。 ------------------------- Re回 79楼yjseu的帖子 太谢谢你了! 问题解决了, 关键是 oss_upload_part_from_file上传的是Part,我误以为是文件。原来官方给的示例,是不管文件多大就文件分成两个part进行发送。 现在修改了下原来的代码,更容易理解了些,下一步准备做的就是,每上传一个part就发送消息去更新进度条。  不知道理解的正确不正确,欢迎指正撒。     aos_file_buf_t * fb = aos_create_file_buf(p);     int res = aos_open_file_for_read(p, G2U("G:\\IEDownLoad\\UCode(IOCP例程).rar"), fb);     int64_t filesize = fb->file_last;     if(filesize<100*1024)     {         AfxMessageBox("文件不能小于100KB");         return ;     }     int64_t partsize = 100 * 1024;     int64_t partupload = 0;     part_num = 1;     while(1)     {         upload_file->file_pos = partsize*(part_num-1);         upload_file->file_last = partsize*part_num; //100k         s = oss_upload_part_from_file(options, &bucket, &object, &upload_id,             part_num, upload_file, &upload_part_resp_headers);         assert(200 == s->code);         part_num++;         partupload += partsize;         if((filesize-partupload < partsize) | (filesize-partupload == partsize))         {             upload_file->file_pos = partsize*part_num;//remain content start pos             upload_file->file_last = get_file_size(G2U("G:\\IEDownLoad\\UCode(IOCP例程).rar"))-partupload;             s = oss_upload_part_from_file(options, &bucket, &object, &upload_id,                 part_num, upload_file, &upload_part_resp_headers);             assert(200 == s->code);             break;         }     } ------------------------- 回 81楼yjseu的帖子 嗯嗯,现在解决了。衷心感谢你们的努力! ------------------------- ReOSS C/CSDK分享交流区 现在有个问题就是,分块的话 不管多大的part 只能 上传成功10个,比如用100KB上传3M 文件,网站上只有1M。(程序调试没有出现错误,不知道网站有没有给错误响应) aos_table_make(p,0); 请问这个语句是什么功能? 我的test_multipart_upload_from_file(LPVOID para) 代码也贴出来吧。 UINT test_multipart_upload_from_file(LPVOID para) {     if (aos_http_io_initialize("oss_test", 0) != AOSE_OK) {         exit(1);     }     Coos_demoDlg * oos_demoDlg = (Coos_demoDlg *)para;     char *object_name = G2U(oos_demoDlg->m_sFilename);     aos_pool_t *p;     aos_string_t bucket;     aos_string_t object;     int is_oss_domain = 1;     oss_request_options_t *options;     aos_status_t *s;     oss_upload_file_t *upload_file;     aos_table_t *upload_part_resp_headers;     oss_list_upload_part_params_t *params;     aos_table_t *list_part_resp_headers;     aos_string_t upload_id;     aos_list_t complete_part_list;     oss_list_part_content_t *part_content1;     oss_complete_part_content_t *complete_content1;     aos_table_t *complete_resp_headers;     int part_num = 1;     int part_num1 = 2;     aos_pool_create(&p, NULL);     options = oss_request_options_create(p);     init_test_request_options(options, is_oss_domain);     aos_str_set(&bucket, TEST_BUCKET_NAME);     aos_str_set(&object, object_name);     //init mulitipart     s = init_test_multipart_upload(options, TEST_BUCKET_NAME, object_name, &upload_id);     assert(200 == s->code);     //upload part from file     upload_part_resp_headers = aos_table_make(p,0);     upload_file = oss_create_upload_file(p);     aos_str_set(&upload_file->filename, G2U(oos_demoDlg->m_sPath));     aos_file_buf_t * fb = aos_create_file_buf(p);     int res = aos_open_file_for_read(p,  G2U(oos_demoDlg->m_sPath), fb);     int64_t filesize = fb->file_last;     int64_t partsize;      filesize/10>100*1024? partsize = filesize/10:partsize = 100*1024;     int64_t partupload = 0;     part_num = 1;     /********** 进度条***************/     //创建用户界面线程,用于进度的显示     oos_demoDlg->m_pUIThread=AfxBeginThread(RUNTIME_CLASS(CcbCopyFile));     if (oos_demoDlg->m_pUIThread == NULL)     {         AfxMessageBox("用户界面线程启动失败!",MB_OK|MB_ICONERROR);         return 0;     }//传递参数     oos_demoDlg->m_pUIThread->PostThreadMessage(WM_THREADINFO,0,(LPARAM)(oos_demoDlg->m_sPath.GetBuffer(0)));     oos_demoDlg->m_pUIThread->PostThreadMessage(WM_THREADINFO,1,(LPARAM)"服务器");     SetTimer(oos_demoDlg->m_hWnd,1,1000,NULL);//速度统计     SetTimer(oos_demoDlg->m_hWnd,2,100,NULL);//操作计时     oos_demoDlg->m_pUIThread->PostThreadMessage(WM_THREADINFO,2,1);//启动     //////////////////////     while(1)     {         if((filesize-partupload < partsize) | (filesize-partupload == partsize))         {             upload_file->file_pos = partupload;//remain content start pos             upload_file->file_last = filesize;             s = oss_upload_part_from_file(options, &bucket, &object, &upload_id,                 part_num, upload_file, &upload_part_resp_headers);                          //**********更新进度****************/             oos_demoDlg->m_nSpeed1 = partupload;             oos_demoDlg->m_pUIThread->PostThreadMessage(WM_THREADINFO, 3,                 (LPARAM) int((partupload*1.0/filesize)*100));             /////////////////////////////             assert(200 == s->code);             break;         }         upload_file->file_pos = partsize*(part_num-1);         upload_file->file_last = partsize*part_num; //100k         s = oss_upload_part_from_file(options, &bucket, &object, &upload_id,             part_num, upload_file, &upload_part_resp_headers);         part_num++;         partupload += partsize;         //**********更新进度****************/         oos_demoDlg->m_nSpeed1 = partupload;         oos_demoDlg->m_pUIThread->PostThreadMessage(WM_THREADINFO, 3,             (LPARAM) int((partupload*1.0/filesize)*100));         /////////////////////////////         assert(200 == s->code);     }     //发送结束消息,用于关闭进度显示模块     oos_demoDlg->m_pUIThread->PostThreadMessage(WM_THREADINFO, 10, 1);     oos_demoDlg->KillTimer(1);     oos_demoDlg->KillTimer(2);     //////////////////     //list part     list_part_resp_headers = aos_table_make(p, 0);     params = oss_create_list_upload_part_params(p);//所有分块信息存储在oss_list_upload_part_params_t的params中     aos_str_set(&params->part_number_marker, "");     params->max_ret = 10;     params->truncated = 0;     aos_list_init(&complete_part_list);     s = oss_list_upload_part(options, &bucket, &object, &upload_id, params, &list_part_resp_headers);//获取所有已上传的块信息     assert(200 == s->code);     //通过aos_list_for_each_entry对part_list进行遍历。     aos_list_for_each_entry(oss_list_part_content_t, part_content1, &params->part_list, node){         complete_content1 = oss_create_complete_part_content(p);         aos_str_set(&complete_content1->part_number, part_content1->part_number.data);         aos_str_set(&complete_content1->etag, part_content1->etag.data);         aos_list_add_tail(&complete_content1->node, &complete_part_list);     }     //complete multipart     complete_resp_headers = aos_table_make(p, 0);     s = oss_complete_multipart_upload(options, &bucket, &object, &upload_id,         &complete_part_list, &complete_resp_headers);    //接口,完成分块上传     assert(200 == s->code);     aos_pool_destroy(p);     AfxMessageBox("上传成功");     //delete object_name;     aos_http_io_deinitialize();     return 0; } ------------------------- ReOSS C/CSDK分享交流区 可算搞定了,params->max_ret = 10; 应该就是最大Part数,真是一步一艰难啊 虽然还是有好多语句不懂,

小弟叶良辰 2019-12-02 02:32:04 0 浏览量 回答数 0
阿里云大学 云服务器ECS com域名 网站域名whois查询 开发者平台 小程序定制 小程序开发 国内短信套餐包 开发者技术与产品 云数据库 图像识别 开发者问答 阿里云建站 阿里云备案 云市场 万网 阿里云帮助文档 免费套餐 开发者工具 云栖号物联网 小程序开发制作 视频内容分析 企业网站制作 视频集锦 代理记账服务 2020阿里巴巴研发效能峰会 企业建站模板 云效成长地图 高端建站 云栖号弹性计算 阿里云云栖号 云栖号案例 云栖号直播