언어&플랫폼/Android 2015. 10. 15. 15:50

oncreate에서 

mWvWebView.loadUrl("javascript:myfunctoin(\"2al\")"); 로 바로 실행하였더니 javascript 함수가 실행하지 않고 다음과 같은 로그가 뜬다.


Uncaught ReferenceError: testAlert is not defined



WebViewClient를 구현한 클래스에서 onPageFinished 함수를 오버라이딩 하여

그 부분에서 자바스크립트 함수를 실행하면 된다.


페이지가 전부 로드되기도 전에 함수를 실행하려 해서 안되었나보다.




posted by cozyboy
:
언어&플랫폼/Android 2015. 6. 29. 20:07

인증모듈때문에 NICE ID 페이지와 연동하는 부분이 있었는데 키캣은 잘 동작하였으나 롤리팝에서 was loaded over HTTPS, but is submitting data to an insecure location at 와 같은 로그가 찍혔다.


TLS/SSL Default Configuration Changes

These changes may lead to breakages in HTTPS or TLS/SSL connectivity in a small number of cases listed below.
이러한 변화는 아래 의 경우 소수 HTTPS 또는 TLS / SSL 연결 의 파손 으로 이어질 수 있습니다.


5.0의 변화부분에 위와 같은 글이 있었고, 아래글과 같은 과정으로 해결을 하였다.





안드로이드 롤리팝 Webview 에서 발생한 문제들..
몇일전부터 안드로이드 5.0 버전으로 테스트중인 Nexus 5 에서 결제작업을 연동중에

문제점들이 발견되기 시작했다.

첫번째 : 의외로 간단하게 해결된 문제

HTTPS > HTTP 전송시 내장 브라우저에서 block 시켜 데이터 전송이 안되는 문제였다. 


[blocked] The page at 'https://xxx' was loaded over HTTPS, but ran insecure content from http://xxx.css': this content should also be loaded over HTTPS.


라는 메세지를 콘솔창으로 마구 뱉는 문제였다...

이 문제는 롤리팝에서 변경된 문제였다.

구글링 해보았으나 실제로 안드로이드 관련정보는 찾을수 없었고

해결방안은 Anroid 5.0 Changes 를 보고 찾을 수 있었다.

WebView



If your app targets API level 21 or higher:
  • The system blocks mixed content and third party cookies by default. To allow mixed content and third party cookies, use the setMixedContentMode() and setAcceptThirdPartyCookies() methods respectively.
  • The system now intelligently chooses portions of the HTML document to draw. This new default behavior helps to reduce memory footprint and increase performance. If you want to render the whole document at once, disable this optimization by calling enableSlowWholeDocumentDraw().
  • If your app targets API levels lower than 21: The system allows mixed content and third party cookies, and always renders the whole document at once.


혼합된 컨텐츠와 서드파티 쿠키가 설정에 따라 Webview 에서 Block 시키는 게 기본이 됬다는 내용이였다.


public abstract void setMixedContentMode (int mode)


Configures the WebView's behavior when a secure origin attempts to load a resource from an insecure origin. By default, apps that target KITKAT or below default to MIXED_CONTENT_ALWAYS_ALLOW. Apps targeting LOLLIPOP default toMIXED_CONTENT_NEVER_ALLOW. The preferred and most secure mode of operation for the WebView is MIXED_CONTENT_NEVER_ALLOW and use of MIXED_CONTENT_ALWAYS_ALLOW is strongly discouraged.


MIXED_CONTENT_ALWAYS_ALLOW : 항상 허용



MIXED_CONTENT_COMPATIBILITY_MODE : 호환성 모드



MIXED_CONTENT_NEVER_ALLOW : 허용 안함


해결 소스

if(android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
set.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptCookie(true);
cookieManager.setAcceptThirdPartyCookies(mWeb, true);
}




http://developer.android.com/about/versions/android-5.0-changes.html#ssl

롤리팝(5.0) change log 를 살펴보시면

TLSv1.1과 TLSv1.2, AES-GCM(AEAD)가 지원되고

MD5, 3DES, ECDH등은 더이상 지원하지 않는다고 합니다.

TLS/SSL 기본 설정값이 달라졌기 때문에, 서버가 MD5나 3DES만 지원한다면, 이것을 먼저 고쳐야 한다는 내용인 듯 싶어요




참고, 펌

http://www.masterqna.com/android/40747/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EB%A1%A4%EB%A6%AC%ED%8C%9D%EC%97%90%EC%84%9C-ssl-https-%ED%86%B5%EC%8B%A0%EC%9D%B4-%EC%95%88%EB%90%A9%EB%8B%88%EB%8B%A4

http://kalesst.blogspot.kr/2015/01/android-50-lollipop-webview-issue.html


posted by cozyboy
:
언어&플랫폼/Android 2015. 6. 18. 17:05



IDE : android studio


샘플 코드 주소git clone https://github.com/googlesamples/google-services.git


사용 코드google-services/android/gcm


프로젝트 import : 외부 프로젝트 import 로 실행



과정 참고 : https://developers.google.com/cloud-messaging/android/start

위 싸이트의 설명에 기반한 샘플코드



 https://developers.google.com/cloud-messaging/android/start 에서 설정 파일 받기




위에서 다운받은 google-services.json 파일을 내 프로젝트의 app/ 폴더로 옮긴다.


위에 적힌 Server API key 값을 

GcmSender.java 31 째 줄에 있는 API_KEY에 기입한다.





PUSH 테스트

환경변수에 JAVA_HOME 설정 ( 내컴퓨터 ->속성 -> 설정변경 -> 고급 _> 환경변수)

각자 Jdk가 깔려있는 폴더를 적어두자(java.exe, javaw.exe 같은 파일이 있는 폴더)

위 설정을 하지 않으면 샘플 push 프로그램이 동작하지 않는다.


브로드캐스트 push

1. cmd.exe 를 실행

2. 소스가 깔려있는 곳으로 이동

$ cd {소스폴더경로}\gcm

$ gradlew.bat run -Pargs="푸쉬 할 메시지"

위와 같이 하면 내 어플리케이션이 설치된 모든 앱들에 "What!!!! the"란 문구의 노티피케이션이 뜬다.



유니캐스트 push

유니캐스트 push를 하려면 내 폰이 발급받은 registration id를 알아야 한다.

RegistrationIntentService 클래스에서 57 line에 
Log.i(TAG, "GCM Registration Token: " + token);

이 있다. 이값이 내폰의 레지스트 아이디 값인데 logcat에서 "RegIntentService"로 필터를 해서 키값을 기억하고 있자.


$ gradlew.bat run -Pargs="푸쉬 할 메시지, {레지스트 아이디}"

를 실행하면 특정 폰에만 push가 가게 된다.


위의 registration id를 자신의 서버에 저장해두어 관리해야 나중에 push를 자유롭게 할 수 있겠다.





GcmSender

push 형태를 보면

https://android.googleapis.com/gcm/send 주소에

request 에 서버키를 설정한후

{message:{내매세지}, to:{특정 폰의 레지스트 아이디}} 형태의 json Data를 write 하는 것을 볼 수 있다.


posted by cozyboy
:
언어&플랫폼/Android 2015. 6. 12. 16:31

redo : ctrl + z

forward : ctrl + shift + z


File > Settings > Keymap

Keymaps 선택할 수 있는 선택박스가 있는데 Eclipse 선택하면 완벽히는 아니어도 이클립스처럼 사용할 수 있다.


Editing

 

Ctrl + Space : 기본 코드 완성

Ctrl + Shift + Space : 스마트 코드 완성(예상되는 타입의 메소드또는 변수명 )

Ctrl + Q : 빠른 문서보기

Shift + F1 : 외부 문서보기(http://developer.android.com/reference로 이동)

Ctrl + mouse over code : 간단한 설명.

Alt + Insert : Generate code( Getters, Setters, Constructors, hashCode/equals, toString )

Ctrl + O : Override methods

Ctrl + I : Implement methods

Ctrl + Alt + T : Surround with… (if..else, try..catch, for, synchronized, etc.)

Ctrl + / : 한줄주석

Ctrl + Shift + / : 블럭주석

Ctrl + W : 연속적인 코드블럭 선택

Alt + Enter : 빠른수정.

Ctrl + Alt + L : Reformat code
Ctrl + Alt + O : Optimize imports
Ctrl + Alt + I : Auto-indent line(s)

Ctrl + Shift + V : 이전에 클립보드에 복사한 히스토리 열기.

Ctrl + D : 라인복제 또는 선택블록 복제

Ctrl + Y : 라인삭제

Ctrl + Shift + J : 라인합치기(Smart line join)

Ctrl + Enter : 라인분리(Smart line split)

Ctrl + Shift + U : 대소문자 변환

Ctrl + Shift + ] / [ : 코드블럭 처음또는 끝까지 선택

Ctrl + Delete : 단어끝까지 삭제

Ctrl + Backspace : 단어처음까지 삭제

 

 

 

Search/Replace

 

Double Shift : 모든곳에서 찾기.

Ctrl + F : 찾기

F3 : 다음찾기

Shift + F3 : 이전찾기

Ctrl + R : 바꾸기

Ctrl + Shift + F : 경로에서 찾기(Find in path)
Ctrl + Shift + R : 경로에서 바꾸기(Replace in path)

 

 

 

Usage Search

 

Alt + F7 / Ctrl + F7 : 사용내용 전체찾기 / 파일에서 사용한것 찾기
Ctrl + Shift + F7 : 현재파일에서 하이라이트
Ctrl + Alt + F7 : 사용된것 새창으로 보여줌.

 

 

 

Compile and Run

 

Shift + F10 : Run

 

 

 

Debugging


F8 : Step over
F7 : Step into
Shift + F7 : Smart step into
Shift + F8 : Step out
Alt + F9 : Run to cursor
Alt + F8 : Evaluate expression
F9 : Resume program
Ctrl + F8 : Toggle breakpoint
Ctrl + Shift + F8 : View breakpoints

 

 

 

Navigation


Ctrl + N : 클래스 열기
Ctrl + Shift + N : 파일열기
Ctrl + Alt + Shift + N : Go to symbol
Alt + Right/Left : 문서탭이동

F12 : 이전에 사용한 도구창 열기

Shift + Esc : 마지막에 사용한 도구창 닫기
Ctrl + G : 줄번호로 이동.
Ctrl + E : 이전에 열었던파일 목록창 열기
Ctrl + B or Ctrl + Click : Go to declaration
Ctrl + Alt + B : Go to implementation(s)
Ctrl + Shift + I : Open quick definition lookup
Ctrl + Shift + B : Go to type declaration
Ctrl + U : super-method/super-class 이동.
Alt + Up/Down : 이전/다음 함수 이동

Ctrl + ] / [ :  코드블럭 처음/끝 이동
Ctrl + F12 : 파일 구조보기

F2 / Shift + F2 : 다음/이전 하이라이트된 에러로 이동.
F4 : 해당 소스로 이동

 

 

 

Refactoring

 

F5 : 복사
F6 : 이동
Alt + Delete : 안전하게 삭제(지우기전에 사용된곳 확인 가능)

Shift + F6 : 이름바꾸기

 

 

 

Live Templates


Ctrl + Alt + J : Surround with Live Template
Ctrl + J : Insert Live Template
iter : Iteration according to Java SDK 1.5 style
inst : Check object type with instanceof and downcast it
itco : Iterate elements of java.util.Collection
itit : Iterate elements of java.util.Iterator
itli : Iterate elements of java.util.List
psf : public static final
thr : throw new


출처 http://blog.naver.com/komseki/130185867089

posted by cozyboy
:
언어&플랫폼/Android 2015. 6. 12. 10:50



절차 

1. 웹뷰 인터페이스 만들기

2. webview에서 intent를 활용해 파일 선택하여 경로 얻기

3. javascript에서 android 함수 호출하기(하이브리드앱-웹뷰와 모바일 브라우저 구분해서 호출)


안드로이드 샘플 코드 -> 웹서버 샘플 코드



안드로이드 샘플 코드

package com.example.i.test1;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.webkit.JavascriptInterface;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.widget.Toast;


public class MainActivity extends Activity {

private WebView mWebView;
private WebViewInterface mWebViewInterface;


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mWebView = (WebView) findViewById(R.id.activity_main_webview);
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
mWebView.setWebChromeClient(new WebChromeClient());
mWebView.setWebViewClient(new MyAppWebBiewClient());

mWebViewInterface = new WebViewInterface(MainActivity.this, mWebView); //JavascriptInterface 객체화

mWebView.addJavascriptInterface(mWebViewInterface, "Android"); //웹뷰에 JavascriptInterface를 설정

//인자로는 인터페이스 객체와, javascript에서 사용될 객체이름(window.Android)


mWebView.loadUrl("http://내 웹서버/");
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();

//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}

return super.onOptionsItemSelected(item);
}

@Override
public void onBackPressed() {
if(mWebView.canGoBack()){
mWebView.goBack();
}
else{
super.onBackPressed();
}
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch(requestCode) {
case 1: {
if (resultCode == RESULT_OK){
Uri uri = data.getData();
String filePath = uri.getPath();
Toast.makeText(this, filePath, Toast.LENGTH_LONG).show();    //intent data로 받은 파일 경로를 출력
}
}
}


}

public class WebViewInterface extends Activity {

private WebView mAppView;
private Activity mContext;

/**
* 생성자.
* @param activity : context
* @param view : 적용될 웹뷰
*/
public WebViewInterface(Activity activity, WebView view) {
mAppView = view;
mContext = activity;

}
/**
* 안드로이드 토스트를 출력한다. Time Long.
* @param message : 메시지

*/
@JavascriptInterface
public void toastLong (String message) {
Toast.makeText(mContext, message, Toast.LENGTH_LONG).show();
Intent chooseFile;
Intent intent;
chooseFile = new Intent(Intent.ACTION_GET_CONTENT);
chooseFile.setType("file/*");
intent = Intent.createChooser(chooseFile, "Choose a file");
mContext.startActivityForResult(intent, 1);
//파일을 오픈할 앱을 선택->파일선택->파일경로 data에 넣고 resultData에 넣어주기
}

/**
* 안드로이드 토스트를 출력한다. Time Short.
* @param message : 메시지
*/
@JavascriptInterface
public void toastShort (String message) { // Show toast for a short time
Toast.makeText(mContext, message, Toast.LENGTH_SHORT).show();
}
}


}


웹서버 샘플 코드

var mobileKeyWords = new Array('iPhone', 'iPod', 'BlackBerry', 'Android', 'Windows CE', 'LG', 'MOT', 'SAMSUNG', 'SonyEricsson');

//모바일인지 체크

    for (var word in mobileKeyWords){

        if (navigator.userAgent.match(mobileKeyWords[word]) != null){

    // 모바일 작업a

            if(window.Android != null) 

                window.Android.toastLong( "JavscriptInterface Test" );

//안드로이드 webviewInterface 사용부분

            break;

        }   

    }


위에서 window.Andriod의 null 체크를 하는 이유는, 웹뷰를 사용한 하이브리드 앱과 모바일 브라우져에서 접속했을때를 구분하기 위해서이다. null 체크를 하지 않는다면 모바일 브라우져에서 페이지를 직접 열때 스크립트 오류가 발생할 것이다.






참고

- webView DOC

http://developer.android.com/reference/android/webkit/WebView.html


-webView Code

http://arabiannight.tistory.com/54

http://tjandroid.blogspot.kr/2013/02/webview.html

- addJavaInterface DOC

http://developer.android.com/reference/android/webkit/WebView.html#addJavascriptInterface(java.lang.Object, java.lang.String)


- Javascript interface(WebviewInterface) 사용

http://fimtrus.tistory.com/76


- 파일열기 intent

http://twigstechtips.blogspot.kr/2011/08/android-how-to-select-file.html


- 모바일 agent 구분하기

http://faildev.blogspot.kr/2012/10/javascript-mobile-agent.html





posted by cozyboy
:
언어&플랫폼/Html/JQuery 2015. 5. 20. 10:52



$("#validate").submit(function( event ) {

// do something...


event.preventDefault();

});

$("#validate").submit(); 



버튼 클릭 이벤트안에 위 구문을 넣으면 리플레쉬없이 submit을 보낼수 있다.


'언어&플랫폼 > Html/JQuery' 카테고리의 다른 글

jquery datatable synchronous  (0) 2015.04.17
jquery 이벤트 찾기  (0) 2015.04.17
css 가운데 정렬  (0) 2013.11.04
[css] body 100% height  (0) 2013.10.18
[jquery] html 조작  (0) 2013.10.17
posted by cozyboy
:
언어&플랫폼/Html/JQuery 2015. 4. 17. 17:34



function initDataTables(id, ajax, columns){

$(id).DataTable( {

"ajax": {"url":ajax, "async":false},

"columns":columns,

"oLanguage": {

   "sSearch": "",

   "sLengthMenu": "<span>_MENU_</span>"

},

"sDom": "T<'row'<'col-md-6 col-xs-12 'l><'col-md-6 col-xs-12'f>r>t<'row'<'col-md-4 col-xs-12'i><'col-md-8 col-xs-12'p>>",

});

}

'언어&플랫폼 > Html/JQuery' 카테고리의 다른 글

refresh 없이 submit  (0) 2015.05.20
jquery 이벤트 찾기  (0) 2015.04.17
css 가운데 정렬  (0) 2013.11.04
[css] body 100% height  (0) 2013.10.18
[jquery] html 조작  (0) 2013.10.17
posted by cozyboy
:
언어&플랫폼/Html/JQuery 2015. 4. 17. 17:28

'언어&플랫폼 > Html/JQuery' 카테고리의 다른 글

refresh 없이 submit  (0) 2015.05.20
jquery datatable synchronous  (0) 2015.04.17
css 가운데 정렬  (0) 2013.11.04
[css] body 100% height  (0) 2013.10.18
[jquery] html 조작  (0) 2013.10.17
posted by cozyboy
:
언어&플랫폼/Codeigniter 2015. 4. 7. 15:32

환경 : Ubuntu 14.04.1 LTS \n \l

WAS : apach2


moe_rewrite module 활성화?

$ sudo a2enmod rewrite

$ sudo service apache2 restart



{CI 폴더}/application/config/config.php 수정

$config['index_page'] = '';



{document root}/.htaccess 수정/생성

<IfModule mod_rewrite.c>

    RewriteEngine On

    RewriteCond %{REQUEST_FILENAME} !-f

    RewriteCond %{REQUEST_FILENAME} !-d

    RewriteRule ^(.*)$ index.php/$1 [L]


    <Files "index.php">

    AcceptPathInfo On

    </Files>

</IfModule>             



/etc/apach2/site-available/000-default.conf 수정

<Directory "/var/www/html"> AllowOverride All </Directory>


$ sudo service apache2 restart









참고


http://stackoverflow.com/questions/1445385/how-to-remove-index-php-in-codeigniters-path


http://www.dev-metal.com/enable-mod_rewrite-ubuntu-14-04-lts/

'언어&플랫폼 > Codeigniter' 카테고리의 다른 글

[codeigniter] mongodb 연동  (0) 2015.04.01
posted by cozyboy
:
언어&플랫폼/Codeigniter 2015. 4. 1. 22:11

환경 : Ubuntu 14.04.1 LTS

 

codeigniter mongoDB 설치 되어있다는 가정하에 진행한다.

 

codeigniter 다운로드 주소 

http://www.codeigniter.com/download


 

 

  1. PHP Driver 설치

 

$ sudo pecl install mongo

 

 

$ php -i | grep 'Configuration File'

Configuration File (php.ini) Path => /etc/php5/cli

Loaded Configuration File => /etc/php5/cli/php.ini

 

php.ini 수정 (/etc/php5/cli/php.ini)

extension=mongo.so

 

 

$ sudo apt-get install php5-dev php5-cli php-pear

 

 

  1. Cogeigniter mongodb library 다운 설치

$ git clone https://github.com/vesparny/cimongo-codeigniter-mongodb-library.git

$ cd cimongo-codeigniter-mongodb-library/

$ cp config/* /var/www/html/Ci/application/config/

$ cp libraries/* /var/www/html/Ci/application/libraries/ -rf

 

 

  1. DB 정보 설정 (자신의 DB 세팅에 맞게 설정)

$ vim /var/www/html/Ci/application/config/cimongo.php 

// Generally localhost

$config['host'] = "localhost";

// Generally 27017

$config['port'] = 27017;

// The database you want to work on

$config['db'] = "test";

// Required if Mongo is running in auth mode

$config['user'] = "";

$config['pass'] = "";

 

  1. mongodb 사용하기

    • 기본 컨트롤러 정하기( Ci/application/config/routes.php)

$route['default_controller'] = "login";

 

  • 라이브러리 자동 로드(Ci/application/config/autoload.php)

$autoload['libraries'] = array('cimongo/cimongo');

 

//자동으로 라이브러리를 부르지 않으려면 컨트롤 페이지에

//$this->load->library("cimongo/cimongo"); 로드 라이브러리를 사용해야 한다.

 

  • cimongo 라이브러리 사용 ( Ci/controllers/login.php)

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Login extends CI_Controller {

public function index()

{

$this->load->view('login');     //페이지 login.php 부르기

}

 

public function test()

{

$count= $this->cimongo->count_all('job');

echo $count;

 

$mongo_data = $this->cimongo->get("job");

foreach($mongo_data->result_array() as $row) {

echo sprintf('x:%d,y:%s <br>',$row['rank'], $row['url']);

}

 

 

}

}

?>

 

  • 동작 확인 (Ci/application/view/login.php 삽입된 js 파일 호출부분)

function test(){

$.ajax({

url:'index.php/login/test/',

success : function(data) {

console.log(data);

 },

 error : function(request, status, error) {

console.log("code:"+request.status+"\n"+"message:"+request.responseText+"\n"+"error:"+error);

 },

});

 

}

 

$(document).ready(function() {

test();

});

 

 


 

  • 라이브러리 사용

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Welcome extends CI_Controller
{
  // Insert Operation
 
public function mongo_insert_test()     
  {
     $this->load->library("cimongo/cimongo");
    
for($i=0;$i<25;$i++) {
        $this->cimongo
            ->insert("testData", array("x" => $i, "y" => 25-$i ));
    
}
  }

// Select Operation
 
public function mongo_select_test()
  {
     $this->load->library("cimongo/cimongo");
    
$mongo_data = $this->cimongo->get("testData");
     foreach($mongo_data->result_array() as $row) {
        echo sprintf('x:%d,y:%d <br>',$row['x'],$row['y']);
    
}
  }
 
  // Update Operation
 
public function mongo_update_test()
  {
     $this->load->library("cimongo/cimongo");
    
$result = $this->cimongo->where(array("x" => 24 ))
                    ->set(array("x" => 25 ))->update("testData");
    
echo $result
  }

// Delete Operation
 
public function mongo_delete_test()
  {
     $this->load->library("cimongo/cimongo");
    
$result = $this->cimongo->where(array("x" => 25 ))
                    ->delete("testData");
    
echo $result;
  }

}

?>

 


 


 



 



[참고]

mongoDB Driver 설치

http://docs.mongodb.org/ecosystem/drivers/php/

 

PHP Fatal error:  Class 'MongoClient' not found  문제 해결

http://stackoverflow.com/questions/24533938/class-mongoclient-not-found

 

cimongo 함수 사용

https://txcom2003.wordpress.com/2015/02/04/codeigniter-tokumx/

 

참고만

http://mudchobo.tistory.com/522

'언어&플랫폼 > Codeigniter' 카테고리의 다른 글

[codeigniter] ubuntu index.php 죽이기  (0) 2015.04.07
posted by cozyboy
:
언어&플랫폼/python 2015. 3. 25. 08:50
설치 
pip install crontab


임포트
from crontab import CronTab


사용자 관련 크론탭 가져오기
cron = CronTab(user='min')

print cron[0]

# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/



새로운 작업 추가
echo = cron.new(command='echo aaa', comment="COM")     
// * * * * * echo aaa # COM


작업 시간 변경
job.minute.during(5,50).every(5)
job.hour.every(4)
job.day.on(4, 5, 6)

job.dow.on('SUN')
job.month.during('APR', 'NOV')

job.setall(2, 10, '2-4', '*/2', None)
job.setall('2 10 * * *')


작업내용 변경
job.set_command("new_script.sh")
job.set_comment("New ID or comment here")


작업 활성/비활성화
job.enable()
job.enable(False)
False == job.is_enabled()


문법체크 
job.is_valid()


작업검색
1. 커맨드
iter = cron.find_command('bar')

2. 커맨트
iter = cron.find_comment('ID or some text')
3. 스케줄
iter = cron.find_time(2, 10, '2-4', '*/2', None)
iter = cron.find_time("*/2 * * * *")


작업삭제

cron.remove( job )
cron.remove_all('echo')
cron.remove_all(comment='foo')
cron.remove_all(time='*/2')



내용 : https://pypi.python.org/pypi/python-crontab



'언어&플랫폼 > python' 카테고리의 다른 글

[python] 파이썬 로깅모듈 (펌)  (0) 2015.03.24
[python] full traceback 쓰기  (0) 2015.03.24
[python] config 설정 요약(ConfigParser)  (0) 2015.03.17
[python] 리스트 랜덤 선택  (0) 2015.01.20
[python] time 관련  (0) 2015.01.06
posted by cozyboy
:
언어&플랫폼/python 2015. 3. 24. 20:52

펌 : http://gyus.me/?p=418


정리가 매우 깔끔한.. 


파이썬 로깅모듈에 대해서

나는 개발자 경력을 자바개발자로 시작했다.

제일 먼저 배운 메서드는 main 메서드이고 그 다음으로 배운건System.out.println 이다.
그러다가 log4j라는 고마운 녀석을 알게되어서 별 생각없이 log4j만 열심히 쓰다가, 여러 로깅모듈을 하나의 인터페이스로 모아주는slf4j를 살짝 만져보다가 nodejs로 전향해서 엄청나게 삽질을 해댄 경험이 있다.

흑역사 링크

지금 개발이 메인언어는 nodejs이고 프로젝트 빌드 및 배포는 chef +fabric으로 하고 있고, 서브 스크립트 언어로 python과 shell을 사용하고 있다. 그중에 스케줄러로 돌아가는 파이썬 스크립트를 만들게 되었는데, 이 녀석이 돌다가 에러가 났을 때 print 메서드 만으로는 이게 실행이 됐는지 죽었는지 확인할 길이 없었다. 그래서 파이썬 로깅모듈을 찾아봤다.

python-logging1.png

어라?! 제일 위에 표준 라이브러리가 나온다.

뭔가 내용이 많은데, 표준라이브러리 내용이 읽기 부담 스러운 분은 이 글을 읽으면 조금 도움이 될지도 모르겠다.

일단, 로깅 라이브러리라고 하면 쉽게 말하면 로그를 찍는 기능이 기본이고, 두번째는 여러군데에 찍는 것이고 (예를 들어 아웃풋 스트림에 찍고, 파일로 찍고), 세번째는 이쁘게 찍는것 이다.

그래서 내가 원하는 기능이 있는지 찬찬히 살펴보았다. 필요한 기능은 아래와 같았다.

  1. 스트림과 파일에 동시에 로그를 남긴다.
  2. 로그를 찍은 시간과 어디에서 로그를 남겼는지 남아야한다.
  3. 테스트 환경과 프로덕션 환경에서 남기는 로깅 레벨이 달라야한다.
  4. 파일에 남기는 경우, 파일의 크기가 너무 크면 자동으로 하나 더 만들어 주면 좋겠다.
  5. 확장이 쉬우면 좋겠다.

일단 결론만 말하면 위에 말한거 전부 다 된다. 기본 모듈이 이정도라니 정말 놀랍다.

차근 차근 한번 알아보자.

스트림과 파일에 동시에 로그를 남기기

print 메서드로만 로그를 찍어왔다면, 이제 기본 탑재된 logging 모듈을 한번 사용해 보자.

import logging

logging.info("I told you so")
logging.warning("Watch out!")

위의 코드를 실행하면 아래와 같이 나오는데, 그 이유는 logging의 기본 로그 레벨이 WARNING으로 되어 있기 때문이다.

WARNING:root:Watch out!

로그를 전부다 WARNING으로 찍을 수는 없으니 살짝만 건드려 보자.

import logging
logging.basicConfig(level=logging.DEBUG)

logging.debug("디버깅용 로그~~")
logging.info("도움이 되는 정보를 남겨요~")
logging.warning("주의해야되는곳!")
logging.error("에러!!!")
logging.critical("심각한 에러!!")

그러면 아래와 같이 나올 것이다.

DEBUG:root:디버깅용 로그~~
INFO:root:도움이 되는 정보를 남겨요~
WARNING:root:주의해야되는곳!
ERROR:root:에러!!!
CRITICAL:root:심각한 에러!!

로깅 레벨도 지정해 봤으니 파일로도 남겨보자.

import logging
logging.basicConfig(filename='./test.log',level=logging.DEBUG)

logging.info("=========================================")
logging.info("파일에다가 남겨봐요~")
logging.info("=========================================")
logging.debug("디버깅용 로그~~")
logging.info("도움이 되는 정보를 남겨요~")
logging.warning("주의해야되는곳!")
logging.error("에러!!!")
logging.critical("심각한 에러!!")

위의 코드를 실행하면 실행한 폴더에 test.log라는 파일이 생기고 그 파일을 열어보면 아래와 같이 로그가 파일로 남는다. 여러번 실행하면 파일을 덮어 쓰는 것이 아니라, 기존의 로그에 이어서 붙이기를 하게된다.

INFO:root:=========================================
INFO:root:파일에다가 남겨봐요~
INFO:root:=========================================
DEBUG:root:디버깅용 로그~~
INFO:root:도움이 되는 정보를 남겨요~
WARNING:root:주의해야되는곳!
ERROR:root:에러!!!

그럼 이제 원래 하고 싶었던 걸 해보자.
아웃풋 스트림에도 찍어봤고, 파일로도 남겨 봤는데 둘다 동시에 남길려면 어떻게 해야되지? 라는 질문이 생기는데, 둘다 로그를 남길려면 logging.getLogger("로거이름") 이라는 메서드로 얻을 수 있는 logger라는 녀석을 사용해야한다.

logger를 써서 여러군데로 로그를 남기는 것에 대해 간단하게 단계를 설명하면 아래와 같다.

  1. 로거 인스턴스를 만든다.
  2. 스트림과 파일로 로그를 출력하는 핸들러를 각각 만든다.
  3. 1번에서 만든 로거 인스턴스에 스트림 핸들러와 파일핸들러를 붙인다.
  4. 로거 인스턴스로 로그를 찍는다.

말로 설명해 봤으니 코드를 보자.

import logging
import logging.handlers

# 1. 로거 인스턴스를 만든다
logger = logging.getLogger('mylogger')

# 2. 스트림과 파일로 로그를 출력하는 핸들러를 각각 만든다.
fileHandler = logging.FileHandler('./myLoggerTest.log')
streamHandler = logging.StreamHandler()

# 3. 1번에서 만든 로거 인스턴스에 스트림 핸들러와 파일핸들러를 붙인다.
logger.addHandler(fileHandler)
logger.addHandler(streamHandler)

# 4. 로거 인스턴스로 로그를 찍는다.
logger.setLevel(logging.DEBUG)
logger.debug("===========================")
logger.info("TEST START")
logger.warning("스트림으로 로그가 남아요~")
logger.error("파일로도 남으니 안심이죠~!")
logger.critical("치명적인 버그는 꼭 파일로 남기기도 하고 메일로 발송하세요!")
logger.debug("===========================")
logger.info("TEST END!")

위의 코드를 실행시켜 보면 콘솔과 파일에 각각 아래와 같은 로그가 남는다.

===========================
TEST START
스트림으로 로그가 남아요~
파일로도 남으니 안심이죠~!
치명적인 버그는 꼭 파일로 남기기도 하고 메일로 발송하세요!
===========================
TEST END!

로그를 찍은 시간과 어느 파일의 어느 라인에 심어 놓은 로그인지 남기기

로그의 포매팅에 관한 이야기 인데, 이 부분도 파이썬을 개발하는 분들이 이미 표준 logging모듈에 심어두셨다. 위에서는 핸들러를 알아봤다면 이번에 알아볼 녀석은 포매터라는 녀석이다. 내가 알고 싶은건 날짜와 시간, 파일명, 로그레벨, 메세지 이정도가 되겠다. 코드를 만드는 단계를 설명안 해도 될정도로 엄청 간단하므로 그냥 코드로 바로 알아보도록하자.

import logging
import logging.handlers

# 로거 인스턴스를 만든다
logger = logging.getLogger('mylogger')

# 포매터를 만든다
fomatter = logging.Formatter('[%(levelname)s|%(filename)s:%(lineno)s] %(asctime)s > %(message)s')

# 스트림과 파일로 로그를 출력하는 핸들러를 각각 만든다.
fileHandler = logging.FileHandler('./myLoggerTest.log')
streamHandler = logging.StreamHandler()

# 각 핸들러에 포매터를 지정한다.
fileHandler.setFormatter(fomatter)
streamHandler.setFormatter(fomatter)

# 로거 인스턴스에 스트림 핸들러와 파일핸들러를 붙인다.
logger.addHandler(fileHandler)
logger.addHandler(streamHandler)

# 로거 인스턴스로 로그를 찍는다.
logger.setLevel(logging.DEBUG)
logger.debug("===========================")
logger.info("TEST START")
logger.warning("스트림으로 로그가 남아요~")
logger.error("파일로도 남으니 안심이죠~!")
logger.critical("치명적인 버그는 꼭 파일로 남기기도 하고 메일로 발송하세요!")
logger.debug("===========================")
logger.info("TEST END!")

위의 코드를 실행하면 아래와 같이 나온다.

[DEBUG|loggingFormatter.py:24] 2014-09-02 20:39:46,630 > ===========================
[INFO|loggingFormatter.py:25] 2014-09-02 20:39:46,630 > TEST START
[WARNING|loggingFormatter.py:26] 2014-09-02 20:39:46,630 > 스트림으로 로그가 남아요~
[ERROR|loggingFormatter.py:27] 2014-09-02 20:39:46,630 > 파일로도 남으니 안심이죠~!
[CRITICAL|loggingFormatter.py:28] 2014-09-02 20:39:46,631 > 치명적인 버그는 꼭 파일로 남기기도 하고 메일로 발송하세요!
[DEBUG|loggingFormatter.py:29] 2014-09-02 20:39:46,631 > ===========================
[INFO|loggingFormatter.py:30] 2014-09-02 20:39:46,631 > TEST END!

이처럼 포매터의 값만 이리저리 바꿔주면, 내가 원하는 대로 로그를 남길 수 있다!
포매터에 들어가는 변수의 문자열은 아래 링크에서 확인하길 바란다.

logrecord-attributes

다음으로 가보자.

테스트 환경과 프로덕션 환경에서 로그 레벨을 다르게 하고 싶을경우

나는 테스트환경과 프로덕션 환경을 구분하기 위해서 처음에 서버를 세팅할 때 환경변수를 심어놓는다. nodejs모듈에서 사용되는(expressjs) NODE_ENV라는 환경변수명이 있는데 이 값을 미리 테스트 서버와 알파서버, 프로덕션 서버에 각각 다른 값으로 설정을 해둔다. 여기서는 로컬 개발 머신과 테스트 서버만 있다고 가정하고 예제를 만들어봤다.

import os
import logging
import logging.handlers

# 로거 인스턴스를 만든다
logger = logging.getLogger('mylogger')

# 포매터를 만든다
fomatter = logging.Formatter('[%(levelname)s|%(filename)s:%(lineno)s] %(asctime)s > %(message)s')

# 환경변수를 읽어서 로깅 레벨과 로그를 남길 파일의 경로를 변수에 저장한다
if (os.environ['NODE_ENV'] == 'local'):
    loggerLevel = logging.DEBUG
    filename = '/tmp/test.log'
elif(os.environ['NODE_ENV'] == 'test'):
    loggerLevel = logging.DEBUG
    filename = '/home/www/log/testServer.log'
else:
    loggerLevel = logging.INFO
    filename = '/home/www/log/server.log'

# 스트림과 파일로 로그를 출력하는 핸들러를 각각 만든다.
fileHandler = logging.FileHandler(filename)
streamHandler = logging.StreamHandler()

# 각 핸들러에 포매터를 지정한다.
fileHandler.setFormatter(fomatter)
streamHandler.setFormatter(fomatter)

# 로거 인스턴스에 스트림 핸들러와 파일핸들러를 붙인다.
logger.addHandler(fileHandler)
logger.addHandler(streamHandler)

# 로거 인스턴스로 로그를 찍는다.
logger.setLevel(loggerLevel)
logger.debug("===========================")
logger.info("TEST START")
logger.warning("파일 명과 로깅 레벨을 각각 환경마다 다르게 남도록 했어요.")
logger.debug("디버그 로그는 테스트 환경과 로컬 피씨에서남 남는 답니다.")
logger.critical("치명적인 버그는 꼭 파일로 남기기도 하고 메일로 발송하세요!")
logger.debug("===========================")
logger.info("TEST END!")

환경변수 NODE_ENV의 값에 따라 로그가 남는 파일의 경로와 로깅 레벨이 달라졌습니다~

파일로 로그를 남기는 경우 파일이 너무 커지면 자동으로 새로운 파일을 만들어 줬으면…

보통 이런거는 shell 스크립트를 스케줄러로 돌려서 자동으로 돌리거나 하는데, 파이썬에는 RotatingFileHandler라는 놈이 이미 만들어져 있다. 그냥 가져다 쓰면 된다. 정말 감동적인 모듈인듯!

이전에 만들어둔 파일 핸들러를 RotatingFileHandler로 교체해보자.

위에 있는 fileHandler부분만 아래 코드로 교체하면 된다.

fileMaxByte = 1024 * 1024 * 100 #100MB
fileHandler = logging.handlers.RotatingFileHandler(filename, maxBytes=fileMaxByte, backupCount=10)

maxBytes 파라메터는 한개의 파일의 최대 바이트 수 이고, backupCount는 몇개까지 백업파일을 남길것인지 세팅하는 파라메터이다.
위의 세팅 대로라면 100MB 짜리 파일을 10개까지 남기겠다. 라는 의미가 된다. 이제 로그 파일의 용량이 엄청나게 커져서 서버에 용량이 부족할까 걱정하지 않아도 된다~ 야호~~!

눈치가 빠른 사람이라면 logging.handlers 아래에 다른 핸들러들도 많겠구나~ 라는 생각이들것이다.

logging.handlers 링크를 타고 가보면 많은 핸들러들을 볼 수가 있다.

어지간한 기능은 다 넣어본것 같은데 기존에 없는 기능을 추가할려면 어떻게 하지?!

확장이 쉬우면 좋겠다!

에러가 났을 때 mongodb에 그 정보를 저장했으면 좋겠다! 어떻게 하지?

일단 쉬운 방법은 나보다 똑똑한 사람이 만들어 놓은 것을 쓰면 된다. 요즘 세상이 참 좋은 세상이라 구글로 찾으면 내가 생각한건 다있다. ㅎㅎ 근데 가끔 이렇게 찾아도 내 마음에 쏙~ 안들 수도 있다. 그럴 때는 한번 만들어보는 것도 힘들긴 하지만, 도움이 될 때가 많다.

그런 의미에서 다른분들도 이미 뜬 삽이겠지만, 나도 한삽을 더 해보려고 한다. 진짜 기본기능만 되는걸 하나 만들어보자.

참고로, mongodb 모듈로 pymongo가 설치되어 있어야 한다. pip3 install pymongo로 간단히 설치가능하다.
mongodb도 물론 설치가 되어있어야한다. 해당 내용은 이글과는 크게 관계없으므로 생략하겠다.

핸들러를 만드는 순서는 아래와 같다.

  1. mongodb에 로그를 저장할 수 있도록 handler를 만든다.
  2. handler는 logging.Handler를 상속하고 emit 메서드를 구현하면된다.

간단히 만들어본 소스는 아래와 같다.

import logging
from pymongo.connection import Connection
from bson import InvalidDocument


class MongoHandler(logging.Handler):

    def __init__(self, db='mongolog', collection='log', host='localhost', port=None, level=logging.NOTSET):
        logging.Handler.__init__(self, level)
        self.collection = Connection(host, port)[db][collection]

    def emit(self, record):
        data = record.__dict__.copy()

        try:
            self.collection.save(data)
        except InvalidDocument as e:
            logging.error("Unable save log to mongodb: %s", e.message)



if __name__ == '__main__':
    MongoHandler('mongolog', 'test')

테스트용 소스도 만들어보자. 간단히 핸들러를 추가하고 로그를 찍어본다.

import logging
from mongoLogger import MongoHandler

if __name__ == '__main__':
    logger = logging.getLogger('mongoTest')
    logger.setLevel(logging.WARNING)
    logger.addHandler(MongoHandler('mongolog', 'log'))

    logger.debug("test debug")
    logger.info("test info")
    logger.warning("test warning")
    logger.error("test error")
    logger.critical("test critical")

실행 후 mongodb에 들어가서 확인을 해보면 아래와 같이 WARNING이상의 로그가 저장되어 있다.

> db.log.find().pretty();
{
    "_id" : ObjectId("5405c2cc1626051dcf238cfa"),
    "stack_info" : null,
    "exc_text" : null,
    "exc_info" : null,
    "processName" : "MainProcess",
    "lineno" : 11,
    "msecs" : 891.3910388946533,
    "relativeCreated" : 50.26507377624512,
    "process" : 7631,
    "name" : "mongoTest",
    "pathname" : "mongoTest.py",
    "created" : 1409663692.891391,
    "filename" : "mongoTest.py",
    "funcName" : "<module>",
    "threadName" : "MainThread",
    "msg" : "test warning",
    "args" : [ ],
    "module" : "mongoTest",
    "levelno" : 30,
    "thread" : NumberLong("140735296762640"),
    "levelname" : "WARNING"
}
{
    "_id" : ObjectId("5405c2cc1626051dcf238cfb"),
    "stack_info" : null,
    "exc_text" : null,
    "exc_info" : null,
    "processName" : "MainProcess",
    "lineno" : 12,
    "msecs" : 891.618013381958,
    "relativeCreated" : 50.492048263549805,
    "process" : 7631,
    "name" : "mongoTest",
    "pathname" : "mongoTest.py",
    "created" : 1409663692.891618,
    "filename" : "mongoTest.py",
    "funcName" : "<module>",
    "threadName" : "MainThread",
    "msg" : "test error",
    "args" : [ ],
    "module" : "mongoTest",
    "levelno" : 40,
    "thread" : NumberLong("140735296762640"),
    "levelname" : "ERROR"
}
{
    "_id" : ObjectId("5405c2cc1626051dcf238cfc"),
    "stack_info" : null,
    "exc_text" : null,
    "exc_info" : null,
    "processName" : "MainProcess",
    "lineno" : 13,
    "msecs" : 891.7689323425293,
    "relativeCreated" : 50.642967224121094,
    "process" : 7631,
    "name" : "mongoTest",
    "pathname" : "mongoTest.py",
    "created" : 1409663692.891769,
    "filename" : "mongoTest.py",
    "funcName" : "<module>",
    "threadName" : "MainThread",
    "msg" : "test critical",
    "args" : [ ],
    "module" : "mongoTest",
    "levelno" : 50,
    "thread" : NumberLong("140735296762640"),
    "levelname" : "CRITICAL"
}

결론

파이썬에서는 로그를 남기기 위해서 뭘쓸까 고민할 필요가 전혀 없다. 표준 라이브러리가 워낙에 잘되어 있고, 확장 또한 쉽기 때문에 별다른 고민없이 logging 모듈만 잘 공부하면 된다. 나도 필요해서 찾아보고 공부해본 것이지만, 위에서 소개한 것 이외에도 많은 기능들을 가지고 있으므로 아마 거의 대부분의 경우에는 표준 logging모듈로도 충분할 것으로 생각된다.

관심이 있는 사람은 logging-cookbook 페이지를 참고하도록 하자.

'언어&플랫폼 > python' 카테고리의 다른 글

[python] crontab 요약  (0) 2015.03.25
[python] full traceback 쓰기  (0) 2015.03.24
[python] config 설정 요약(ConfigParser)  (0) 2015.03.17
[python] 리스트 랜덤 선택  (0) 2015.01.20
[python] time 관련  (0) 2015.01.06
posted by cozyboy
:
언어&플랫폼/python 2015. 3. 24. 17:25


import traceback
import sys

try:
    do_stuff()
except Exception, err:
    print traceback.format_exc()


import sys, traceback

def run_user_code(envdir):
    source = raw_input(">>> ")
    try:
        exec source in envdir
    except:
        print "Exception in user code:"
        print '-'*60
        traceback.print_exc(file=sys.stdout)
        print '-'*60

envdir = {}
while 1:
    run_user_code(envdir)



python doc : 

https://docs.python.org/2/library/traceback.html


[펌]

http://stackoverflow.com/questions/3702675/print-the-full-traceback-in-python-without-halting-the-program

'언어&플랫폼 > python' 카테고리의 다른 글

[python] crontab 요약  (0) 2015.03.25
[python] 파이썬 로깅모듈 (펌)  (0) 2015.03.24
[python] config 설정 요약(ConfigParser)  (0) 2015.03.17
[python] 리스트 랜덤 선택  (0) 2015.01.20
[python] time 관련  (0) 2015.01.06
posted by cozyboy
:
언어&플랫폼/python 2015. 3. 17. 18:45



설정파일, 섹션, 옵션 생성

import ConfigParser


config = ConfigParser.RawConfigParser()

config.add_section('Section1')

config.set('Section1', 'an_int', '15')

config.set('Section1', 'a_bool', 'true')

config.set('Section1', 'a_float', '3.1415')

config.set('Section1', 'baz', 'fun')

config.set('Section1', 'bar', 'Python')

config.set('Section1', 'foo', '%(bar)s is %(baz)s!')


with open('example.cfg', 'wb') as configfile:

    config.write(configfile)  ##마지막에 꼭 write 해줘야 한다


example.cfg 내용

[Section1]

an_int = 15

a_bool = true

a_float = 3.1415

baz = fun

bar = Python

foo = %(bar)s is %(baz)s!


설정파일 읽기

config = ConfigParser.RawConfigParser()

config.read('example.cfg')


섹션리스트 가져오기

>>> config.sections()

['Section1']


섹션 추가

config.add_section('testadsec')


섹션 제거

config.remove_section('testadsec')


섹션존재 확인

>>> config.has_section('Section1')

True


해당섹션의 옵션, 옵션값  가져오기

>>> config.items('Section1')

[('an_int', '15'), ('a_bool', 'true'), ('a_float', '3.1415'), ('baz', 'fun'), ('bar', 'Python'), ('foo', '%(bar)s is %(baz)s!')]


해당섹션의 옵션만 가져오기

>>> config.options('Section1')

['an_int', 'a_bool', 'a_float', 'baz', 'bar', 'foo']


옵션 얻기

config.get('Section1', 'an_int')

getint('Section1', 'an_int')        #옵션이 인트형일때만 가져옴

getfloat('Section1', 'an_int')      #옵션이 프로트형일때만

getboolean('Section1', 'an_int')   #옵션이 불린형일때만


옵션 변경

config.set('Section1', 'an_int', 2015)


옵션 제거

config.remove_option('Section1', 'an_int')


옵션 배열 설정/읽기

--설정--

a = [1,2,3,4,5]

config.set('Section1', 'an_int', a)

--읽기--

a = json.loads( config.get('Section1', 'an_int'))

(참고 : http://stackoverflow.com/questions/335695/lists-in-configparser)


주석 적기

config.set('Section1', 'an_int', '# 주석은 "#"나 ";" 이다')

config.set('Section1', 'an_int', '15')






doc(13.2 ConfigParser) <- 정리 내용 

https://docs.python.org/2/library/configparser.html#examples


doc(14,2 configparser)

: https://docs.python.org/3/library/configparser.html



'언어&플랫폼 > python' 카테고리의 다른 글

[python] 파이썬 로깅모듈 (펌)  (0) 2015.03.24
[python] full traceback 쓰기  (0) 2015.03.24
[python] 리스트 랜덤 선택  (0) 2015.01.20
[python] time 관련  (0) 2015.01.06
shell과 pipe 실행하기(subprocess)  (0) 2014.03.21
posted by cozyboy
:
언어&플랫폼/python 2015. 1. 20. 11:06


s=set(range(1,6))
import random

while len(s)>0:
  s.remove(random.choice(list(s)))
  print(s)

Three runs give three different answers:

>>> 
set([1, 3, 4, 5])
set([3, 4, 5])
set([3, 4])
set([4])
set([])
>>> 
set([1, 2, 3, 5])
set([2, 3, 5])
set([2, 3])
set([2])
set([])

>>> 
set([1, 2, 3, 5])
set([1, 2, 3])
set([1, 2])
set([1])
set([])


http://stackoverflow.com/questions/306400/how-do-i-randomly-select-an-item-from-a-list-using-python

posted by cozyboy
:
언어&플랫폼/python 2015. 1. 6. 18:14

현재시간

>>> import datetime

>>> a = datetime.datetime.now()

>>> print a

2015-01-07 15:44:35.482103

>>> print a.year, a.month, a.day, a.hour, a.minute, a.second, a.microsecond, a.tzinfo

2015 1 7 15 44 35 482103 None


>>> datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')

'2015-01-07 15:53:01'


시간 비교

>>> from datetime import datetime

>>> 

>>> date_ob = datetime.strptime('16:05', '%H:%M')

>>> print date_ob

1900-01-01 16:05:00

>>> date_ob2 = datetime.strptime('16:10', '%H:%M')

>>> print date_ob2

1900-01-01 16:10:00

>>> print date_ob - date_ob2

-1 day, 23:55:00

>>> print date_ob2 - date_ob

0:05:00


>>> datetime.strptime('Jun 1 2005 1:33PM', '%b %d %Y %I:%M%p')

datetime.datetime(2005, 6, 1, 13, 33)


초 -> 시간

>>> import datetime
>>> str(datetime.timedelta(seconds=666))
'0:11:06'


>>> import time
>>> time.strftime("%H:%M:%S", time.gmtime(666))
'00:11:06'


시간 -> 초

>>> import datetime

>>> import time

>>> 

>>> x = time.strptime('01:01', '%H:%M')

>>> print x

time.struct_time(tm_year=1900, tm_mon=1, tm_mday=1, tm_hour=1, tm_min=1, tm_sec=0, tm_wday=0, tm_yday=1, tm_isdst=-1)

>>>

>>> a = datetime.timedelta(hours=x.tm_hour, minutes=x.tm_min).total_seconds()

>>> print a

3660.0




-------------------------------------------------------


[ 컴퓨터 시간 표현 ]

 

[ 용어 ]

[ 내용 ]

타임스탬프

(TimeStamp)

컴퓨터에서 시간을 측정하는 방법으로 1970년 1월1일 자정

(epoch)이후로 초 단위로 측정한 절대시간 입니다.

협정세계시

(UTC, Universal Time Coordinated)

1972부터 시행된 국제 표준시

(세슘 원자의 진동수에 의거한 초의 길이가 기준이 됩니다)

그리니치 평균시

(GMT, Greenwich Mean Time)

런던 그리니치 천문대의 자오선상에서의 평균 태양시 (1972년

부터 협정세계시를 사용하지만, 동일한 표현으로 널리 쓰임)

지방표준시

(LST, Local Standard Time)

UTC를 기준으로 경도 15도마다 1시간 차이가 발생하는 시간

(한국은 동경 135도를 기준으로 UTC보다 9시간 빠름)

일광절약 시간제

(DST, Daylight Saving Time)

흔히 서머타임으로 알고 있는 것으로, 에너지 절약을 목적

으로 시간을 한 시간씩 앞당기거나 뒤로 미루는 제도.

 

[ struct_time 시퀀스 객체 ]

 

[ 속성 ]

[ 내용 ]

tm_year

년도(예: 1982, 1999, 2009)

tm_mon

월(1~12)

tm_mday

일(1~31)

tm_hour

시(0~23)

tm_min

분(0~59)

tm_sec

초(0~61)

tm_wday

각 요일을 숫자로 나타냅니다. (월요일은 '0' 입니다)

tm_yday

1월 1일부터 오늘까지 누적된 날짜를 반환 (1~366)

tm_isdst

일광절약 시간제(서머타임)를 나타냅니다 (0, 1, -1)

 

[ time 모듈 함수 ]

 

[ 함수 ]

[ 내용 ]

time.time()

1970년 1월 1일 자정 이후로 누적된 초를 float 단위로 반환

time.sleep(secs)

현재 동작 중인프로세스를 주어진 초만큼 정지

time.gmtime([secs])

입력된 초를 변환하여, UTC기준의 struct_time 시퀀스 객체로 반환

(인자가 입력되지 않은 경우, time()을 이용하여 현재 시간을 변환)

time.localtime([secs])

입력된 초를 변환하여, 지방표준시 기준의 struct_time 시퀀스

객체를 반환 (인자가 입력되지 않은 경우, time()을 이용하여 현재

시간을 변환)

time.asctime([t])

struct_time 시퀀스 객체를 인자로 받아서

'Sun Mar 15 18:49:28:2009'와 같은 형태로 반환

time.mktime(t)

지방표준시인 struct_time 시퀀스 객체를 인자로 받아서 time()과

같은 누적된 초를 반환

time.strftime(format,[, t])

struct_time 객체를 사용자가 정의한 형식으로 변경하여

문자열로 반환

time.strptime(string[, format])

사용자가 정의한 형식 문자열을 struct_time 객체로 변환

 

[ 형식 지정자 ]

 

[ 지시자 ]

[ 내용 ]

%y

연도를 축약하여 표시

%Y

연도를 축약하지 않고 표시

%b

축약된 월 이름

%B

축약되지 않은 월 이름

%m

숫자로 표현한 월(01~12)

%d

일(01~31)

%H

24시를 기준으로 한 시(00~23)

%I

12시를 기준으로 한 시(01~12)

%M

분(00~59)

%S

초(00~61)

%p

오전(AM) / 오후(PM)을 표시

%a

축약된 요일 이름

%A

축약되지 않은 요일 이름

%w

요일을 숫자로 표시(예: 일요일(0))

%j

1월 1일부터 누적된 날짜(001~366)

http://devanix.tistory.com/297 내용

posted by cozyboy
:
언어&플랫폼/python 2014. 3. 21. 13:45

#!/usr/bin/python


import subprocess


#mount | grep devpts


p1 = subprocess.Popen(["mount"], stdout=subprocess.PIPE)

p2 = subprocess.Popen(["grep", "devpts"], stdin=p1.stdout, stdout=subprocess.PIPE)

out, err = p2.communicate()


print out

print 'err:'+str(err)

           



[결과]

devpts on /dev/pts type devpts (rw,noexec,nosuid,gid=5,mode=0620)


err:None




'언어&플랫폼 > python' 카테고리의 다른 글

[python] 리스트 랜덤 선택  (0) 2015.01.20
[python] time 관련  (0) 2015.01.06
[python] dictionary 에 dictionary 붙이기  (0) 2013.12.18
[python] 띄어쓰기 제거  (0) 2013.12.10
[python] json decode  (0) 2013.12.10
posted by cozyboy
:
언어&플랫폼/python 2013. 12. 18. 23:34


>>> dest = orig.copy()
>>> dest.update(extra)
>>> orig
{'A': 1, 'C': 3, 'B': 2}
>>> dest
{'A': 1, 'C': 3, 'B': 2, 'E': 5, 'D': 4}


[펌] : http://stackoverflow.com/questions/8930915/python-append-dictionary-to-dictionary

'언어&플랫폼 > python' 카테고리의 다른 글

[python] time 관련  (0) 2015.01.06
shell과 pipe 실행하기(subprocess)  (0) 2014.03.21
[python] 띄어쓰기 제거  (0) 2013.12.10
[python] json decode  (0) 2013.12.10
Tutorial  (0) 2013.12.10
posted by cozyboy
:
언어&플랫폼/python 2013. 12. 10. 17:41


output.strip('\r\n')




[참고] : http://stackoverflow.com/questions/275018/how-can-i-remove-chomp-a-newline-in-python

'언어&플랫폼 > python' 카테고리의 다른 글

shell과 pipe 실행하기(subprocess)  (0) 2014.03.21
[python] dictionary 에 dictionary 붙이기  (0) 2013.12.18
[python] json decode  (0) 2013.12.10
Tutorial  (0) 2013.12.10
os.popen3와 subprocess.Popen  (0) 2013.12.09
posted by cozyboy
:
언어&플랫폼/python 2013. 12. 10. 17:29
json 형식의 str을 json으로 변환

import json


def testJson(output):

    try:

        decoded = json.loads(output)

        print decoded

        print  decoded['stats']['total_space']

        #print "JSON parsing example: ", decoded['stats']['total_space']

        #print "Complex JSON parsing example: ", decoded['two']['list'][1]['item']

    except (ValueError, KeyError, TypeError):

        print "JSON format error




json, pretty json format.

    @staticmethod             

    def decodeJson(output):   

        '''

        Info : 

            Convert json formed string to json

        --------------------------------------------------------------

        Parameter:

            output - json formated String

        --------------------------------------------------------------

        Return:

            if success decode 

                return output(formated json)

            else 

                return -1

        '''

        try:

            decoded = json.loads(output)   

            return decoded

        except (ValueError, KeyError, TypeError):

            if DEBUG: print "JSON format error[decodeJson()]"

            return -1

        

    @staticmethod

    def encodePrettyJson(output):  

        try:

            decoded = json.dumps(output, sort_keys=True, indent=4, separators=(',', ': '))

            return decoded

        except (ValueError, KeyError, TypeError):

            if DEBUG: print "JSON format error[encodePrettyJson()]"

            return -1

       



참조 : http://docs.python.org/2/library/json.html




'언어&플랫폼 > python' 카테고리의 다른 글

[python] dictionary 에 dictionary 붙이기  (0) 2013.12.18
[python] 띄어쓰기 제거  (0) 2013.12.10
Tutorial  (0) 2013.12.10
os.popen3와 subprocess.Popen  (0) 2013.12.09
[python] 로컬 ip 얻기  (0) 2013.11.22
posted by cozyboy
: