보관물

Archive for the ‘Language’ Category

Windows에서 pandas사용시 cx_Freeze로 build 후 실행시 ImportError: Missing required dependencies[‘numpy’] 해결 하는 방법

3월 24, 2017 댓글 남기기

문제 발생 환경 정보

  • Windows 8.1 K
  • Python 3.4.4 (32bit)
  • cx-Freeze 4.3.4
  • pandas 0.19.2
  • numpy 1.12.0

기존 application의 요건이 추가되어 pandas를 사용하게 되었다.
작업이 마무리 되어 cx_Freeze로 build를 수행할때까지는 별 문제가 없었지만 exe를 실행해보니 다음과 같은 error가 발생되었다.

cx_Freeze_numpy

결국은 ImportError: Missing required dependencies [‘numpy’] 가 발생한 것인데 build log를 살펴보면 정상적으로 numpy를 추출한 것 같기에 난감한 상황이 되었다.

먼저 setup.py의 buildOptions에 numpy를 명시적으로 적어 주어봤다.

buildOptions = dict(packages=[],
excludes=[‘tkinter’, ’email’, ‘html’, ‘http’, ‘unittest’, ‘urllib’, ‘ctypes’, ‘distutils’],
includes=[‘numpy’, ‘wx.xml’],
include_msvcr=True)

증상은 동일 했다.
packages에도 numpy를 넣어봤지만 역시나 동일한 증상이 발생되며 해결되지 않았다.

일단 찾아보니 cx_Freeze가 작년말(2016년 11월경) 커다란 update가 있었기도 했고 현재 5.0.1 version이 stable version이므로 cx_Freeze를 5.0.1로 재설치하여 다시 시도해 봤다.

문제 해결을 위해 재설치한 환경 정보

  • cx_Freeze 5.0.1

그런데…

ImportError: Missing required dependencies [‘_methods’]

어라? error message가 바뀌었다.
위에 적진 않았지만 error message를 자세히 보니 _methods는 numpy.core package에 있는 _methods.py 였다.
위에 includes에 추가한 numpy 처럼 동일하게 처리 해보았다.

buildOptions = dict(packages=[],
excludes=[‘tkinter’, ’email’, ‘html’, ‘http’, ‘unittest’, ‘urllib’, ‘ctypes’, ‘distutils’],
includes=[‘numpy’, ‘numpy.core._methods’, ‘wx.xml’],
include_msvcr=True)

그랬더니…

ImportError: Missing required dependencies [‘distutils’]

이젠 ImportError가 친근하게 느껴질 정도이다.
excludes에서 distutils를 제거해보니 이번엔 ctypes에서 ImportError가 발생했다.
반복하다 결국 ImportError는 다음과 같은 buildOptions에서 해결되었다.

buildOptions = dict(packages=[],
excludes=[‘tkinter’, ‘html’],
includes=[‘numpy’, ‘numpy.core._methods’, ‘wx.xml’],
include_msvcr=True)

cx_Freeze에서의 ImportError관련 부분은 글을 쓰는 현재 기준(2017.03.24) issue가 등록된 상태이다.

[관련 링크]
conda env: ImportError: Missing required dependencies [‘numpy’]
cx_Freeze 5.0.1 do not find some modules that cx_Freeze 5.0 did
Missing modules in numpy and other packages

위에서 언급하진 않았지만 cx_Freeze를 5.0.1로 변경하였더니 build시 module이 library.zip으로 압축되어 생기질 않았다.
죄다 folder로 풀려버리는 증상이 있었다.

cx_Freeze_module_out

cx_Freeze 5.x로 version up이 되면서 변경사항이 있었는데 이와 연관된 이유인것 같다.
(cx_Freeze release note의 2, 3번 항목 참조)

현재 사용할 수 있는 option중에 몇 가지 방법을 시도해 보다 결국 다음과 같은 식으로 해결을 했다.
다만 library.zip은 더이상 생성되지 않는다. 다만 module 폴더들이 사라진다.

buildOptions = dict(packages=[],
excludes=[‘tkinter’, ‘html’],
includes=[‘numpy’, ‘numpy.core._methods’, ‘wx.xml’],
zip_include_packages=[‘*’],
zip_exclude_packages=[‘numpy’, ‘numpy.core._methods’],
include_msvcr=True)

하지만 이렇게 해도 zip_exclude_packages에 정의한 module은 폴더가 남는다.
원래 module이 폴더로 풀려버리는 증상은 별도 post로 작성하려 했으나 zip_exclude_package 항목때문에 한 post에 묶을 수 밖에 없었다.

zip_exclude_packages에 numpy, numpy.core_methods를 추가하지 않으면 애초에 문제가 되었던 ImportError: Missing required dependencies [‘numpy’]가 다시 발생하게 된다.

현재 issue로 등록되어있듯이 cx_Freeze에서 module import와 관련된 부분 어딘가에 bug가 있는 것 같다.

카테고리:Python

Windows에서 pysftp사용시 cx_Freeze하면 cryptography관련 오류가 발생하는 경우 해결 방법

5월 19, 2016 댓글 남기기

문제 발생 환경 정보

  • Windows 8.1 K
  • Python 3.4.4 (32bit)
  • pysftp 0.2.8
  • cryptography 1.3.2
  • pycrypto 2.6.1
  • paramiko 2.0.0

pysftp를 이용해 아주 간단한 in-house tool을 만들던 중 개발환경에서 바로 실행을 하면 문제가 없던 부분이 packaging을 하니 오류가 발생하는 상황이 발생하였다.

with pysftp.Connection(host=p_host, username=p_username, password=p_password) as sftp:

pysftp의 Connection을 사용하는 부분에서 오류가 발생했고 except로 오류를 잡아 확인해 보니 다음과 같은 오류 메시지가 발생하였다.

Multibackend cannot be initialized with no backends.
If you are seeing this error when trying to use default_backend()
please try uninstalling and installing cryptography

오류 메시지 대로 pip로 cryptography를 다시 설치해 봤지만 문제는 해결되지 않았다.

pysftp는 paramiko에 의존성이 있으므로 paramiko의 debug log를 찍어 좀 더 확인해 보기로 했다.
관련된  source에 다음의 code를 추가하여 log를 확인하였다.

import paramiko
paramiko.util.log_to_file(‘logs/paramiko.log’)

log 내용을 보면 paramiko.transport에서 오류가 시작되었고 호출된 것을 따라가보니
cryptography.hazmat.backends.multibackend의 Multibackend class에서 처음 오류메시지를 발생시키고 있었다.
문제되는 source는 찾았지만 뚜렷한 방법을 찾지 못하던 중 paramiko의 version을 낮춰서 해결했다는 글을 찾을 수 있었다.

paramiko의 changelog를 보면 현재 stable인 2.0.0은 하위호환성이 유지되지 않는다는 내용이 있다.

Warning: This is a backwards incompatible change.

참고로 paramiko 2.0.0은 2016.04.28에 version up 되었지만 pysftp 0.2.8은 2014.05.28이 마지막 release였다.
pip로 pysftp를 설치하게 되면 자동으로 paramiko 2.0.0이 설치되는데 아마도 이번 오류가 아니었다면 신경도 쓰지 않았었을 것 같다.
그렇기때문에 version을 낮추면 해결된다는 것이 어느정도 일리가 있어보이기도 하고 이전에 cx_Freeze의 문제로 python의 version을 낮추어 해결한 적이 있으므로 바로 실행에 옮겨보았다.
paramiko의 1.x 마지막 stable version은 1.17.0이기때문에 1.17.0 version을 설치하였다.

pip uninstall paramiko
pip install paramiko==1.17

그런데 설치가 되지 않았다.

error: Microsoft Visual C++ 10.0 is required (Unable to find vcvarsall.bat)

이전에 DLL관련 문제가 있어서 Microsoft Visual C++ Redistributable package를 몇가지 종류별로 설치해 두었었는데 그때와는 또 다른 상황이다.
이전에는 실행 중 발생하던 오류였다면 이번엔 package를 설치하는 과정에서 발생된 문제이다.

관련해서 구글링을 해보던 중 redistributable package가 아닌 Visual C++ 2010 Express를 설치해야한다는 글이 여러건 발견되어서 Visual C++ 2010 Express 설치본을 찾아 설치하고 다시 paramiko를 설치하니 정상적으로 설치가 되었다.
참고로 python 2.7과 python 3.4를 사용하는 경우 windows에서 module 설치시 Unable to find vcvarsall.bat관련 오류에 대해 잘 정리해 놓은 글이 있어 공유한다.

이제 실행을 해보니 이번엔 다음과 같은 오류가 발생되었다. 산넘어 산이다.

Traceback (most recent call last):
 File “C:/Users/imac/Project/Nuri/contentsUploader/main.py”, line 7, in <module>
  from vs import state
 File “C:\Users\imac\Project\Nuri\contentsUploader\vs\state.py”, line 2, in <module>
   import pysftp
 File “C:\Users\imac\Python3_4_4\lib\site-packages\pysftp.py”, line 10, in <module>
   import paramiko
 File “C:\Users\imac\Python3_4_4\lib\site-packages\paramiko\__init__.py”, line 30, in <module>
   from paramiko.transport import SecurityOptions, Transport
 File “C:\Users\imac\Python3_4_4\lib\site-packages\paramiko\transport.py”, line 50, in <module>
   from paramiko.dsskey import DSSKey
 File “C:\Users\imac\Python3_4_4\lib\site-packages\paramiko\dsskey.py”, line 26, in <module>
   from Crypto.PublicKey import DSA
 File “C:\Users\imac\Python3_4_4\lib\site-packages\Crypto\PublicKey\DSA.py”, line 89, in <module>
   from Crypto import Random
 File “C:\Users\imac\Python3_4_4\lib\site-packages\Crypto\Random\__init__.py”, line 28, in <module>
   from Crypto.Random import OSRNG
 File “C:\Users\imac\Python3_4_4\lib\site-packages\Crypto\Random\OSRNG\__init__.py”, line 34, in <module>
   from Crypto.Random.OSRNG.nt import new
 File “C:\Users\imac\Python3_4_4\lib\site-packages\Crypto\Random\OSRNG\nt.py”, line 29, in <module>
   import winrandom
ImportError: No module named ‘winrandom’
Process finished with exit code 1

winrandom을 찾을 수 없다는 얘긴데 pycrypto module에서의 bug였다.
현재는 fix된 source가 최종 release version에 포함되어 있지 않으므로 해당 부분의 소스를 직접 수정 하여 처리하였다. (글을 쓰는 현재 기준 stable version은 2.6.1)

Python3_4_4\Lib\site-packages\Crypto\Random\OSRNG\nt.py 파일의
28 line을 import winrandom 에서 from Crypto.Random.OSRNG import winrandom으로 수정하여 모든 문제를 해결하였다.

카테고리:Python

Windows에서 cx_Freeze로 packaging한 exe실행시 wxLocale관련 오류 해결 방법

4월 20, 2016 1개의 댓글

문제 발생 환경 정보

  • Windows 8.1 K
  • Python 3.5.1 (32bit)
  • wxPython-Phoenix 3.0.3.dev1964+f780b21
  • cx_Freeze 5.0

Python 3.5.1을 사용하기 위해 cx_Freeze 5.0을 이용해 Windows에서 packaging을 하니 sqlite3쪽에서 DLL load failed가 발생하거나 Windows 7에서의 경우는 api-ms-win-core-kernel32-private-l1-1-0.dll이 없다고 하거나 하는 등의 오류가 발생해서 다양한 방법을 시도해보았으나 결국 실패하였다.
(특이한 점은 python main.py와 같은 식으로 직접 실행하면 문제가 없지만 packaging한 exe를 실행할때만 발생한다는 것이다.)
이런 현상은 cx_Freeze뿐만아니라 PyInstaller로 packaging하는 경우도 비슷한 현상이 발생한다.
그래서 굳이 Python 3.5.1을 유지할 필요는 없어 3.4.4로 낮추고 cx_Freeze역시 stable version으로 낮춰 packaging을 하고 실행하였더니 다음과 같은 error가 발생하였다.

Python version을 낮춘 환경 정보

  • Windows 8.1 K
  • Python 3.4.4 (32bit)
  • wxPython-Phoenix 3.0.3.dev1964+f780b21
  • cx_Freeze 4.3.4

cx_Freeze_locale_error

wxLocale을 사용하지 않고 setlocale()을 바로 호출해서 C/C++과 windows locale간에 일치하지 않는다는 내용인데 구글링해보니 생각보다 쉽게 해결되었다.

http://stackoverflow.com/questions/21444951/wxpython-3-0-breaks-older-apps-locale-error

글 내용을 보면 locale정보를 명시적으로 적어주면 해결된다는 애기인지라 현재 source에서 locale설정 부분을 추가해서 packaging을 해보니 error없이 정상적으로 실행되었다.

app = wx.App()
locale = wx.Locale(wx.LANGUAGE_KOREAN)  #추가한 부분
frame = MainFrame(None)
frame.Show(True)
app.MainLoop()

참고로 locale관련된 정보는 wxPython-Phoenix의 Langauge page에서 확인 가능하다.

카테고리:Python

Python 3.5.x에서 cx_Freeze 설치하기

4월 19, 2016 댓글 남기기

wxPython-Phoenix를 사용하여 만든 application을 배포하기 위해 몇가지 방법을 찾아보다 결국 cx_Freeze를 사용하기로 하였다.
현재 기준으로(2016.04.19) cx_Freeze는 release version기준으로 4.3.4까지 나와있다.

당연히 pip를 사용해 해당 module을 설치할 수 있다.

pip install cx_Freeze

하지만 이렇게 설치한 cx_Freeze 4.3.4는 python 3.4까지만 지원을 하기 때문에 현재 개발환경인 python 3.5.1에서는 정상적으로 packaging이 되지 않았다.
좀 더 자세하게 얘기하면 packaging은 되지만 실행을 해보면 알수없는 오류와 함께 실행되지 않는다.

그래서 cx_Freeze를 python 3.5에서 사용할 수 있는 방법을 찾아보다 보니 cx_Freeze 5.0 for Python 3.5 on Windows 글을 찾게 되었다.
글 내용을 보면 2016년 4월 현재 stable version인 cx_Freeze 4.3.4는 Python 3.5를 지원하지 않지만 development version인  cx_Freeze 5.0은 Python 3.5를 지원한다는 내용이 서두에 있다.

글 내용은 Windows관련 내용이지만 cx_Freeze source code를 내려받아 Mac OS X에서도 설치해서 사용해보니 결과적으로 packaging도 잘되고 실행도 잘 되었다.

이번 post에서는 Mac OS X과 Windows에서 설치하는 방법을 모두 정리해보려 한다.

[Max OS X]

  1. cx_Freeze의  bitbucket에서 현재 source를  download한 후 압축을 푼다.
  2. 해당 폴더로 이동한 후 cx_Freeze를 설치한다.

    $ python setup.py install
    running install
    running bdist_egg
    running egg_info
    creating cx_Freeze.egg-info
    writing cx_Freeze.egg-info/PKG-INFO
    …중략…
    Installed /Users/imac/.pyenv/versions/3.5.1/lib/python3.5/site-packages/cx_Freeze-5.0-py3.5-macosx-10.10-x86_64.egg
    Processing dependencies for cx-Freeze==5.0
    Finished processing dependencies for cx-Freeze==5.0

  3. pip로 보면 5.0이 설치된 것을 확인할 수 있다.

    $ pip list
    …중략…
    cx-Freeze (5.0)
    …후략…

[Windows]

windows용은 두 가지 방법이 있다.

  • cx_Freeze 5.0 for Python 3.5 on Windows 글에 있는 대로 cx_Freeze source code로 부터 wheel을 만들어 pip로 설치하는 방법
  • cx_Freeze 5.0 for Python 3.5 on Windows 글이 있는 github에서 제공하는 wheel을 download받아 pip로 설치하는 방법

현재 기준 (2016.04.19)으로 cx_Freeze source code의 마지막 commit은 2016.03.29이고 wheel의 마지막 commit은 2016.04.09이라서 최종 source를 반영했다는 가정을 한다면 둘 중 편한 방법을 선택하면 된다.
이번 post에서는 간단하게 하기위해 wheel을 download받아 설치하였다.

  1. cx_Freeze 5.0 for Python 3.5 on Windows 글에서 wheel을 download 한다.
  2. 해당 폴더로 이동한 후 cx_Freeze를 설치한다.
    (현재 windows에 설치된 python이 32bit라서 cx_Freeze-5.0-cp35-cp35m-win32.whl파일을 사용하였다.
    python 64bit를 사용하고 있다면 cx_Freeze-5.0-cp35-cp35m-win_amd64.whl 파일을 사용하면 된다.)

    > pip install cx_Freeze-5.0-cp35-cp35m-win32.whl
    Processing c:\users\imac\downloads\cx_freeze-wheels-master\cx_freeze-wheels-master\cx_freeze-5.0-cp35-cp35m-win32.whl
    Installing collected packages: cx-Freeze
    Successfully installed cx-Freeze-5.0

  3. pip로 보면 5.0이 설치된 것을 확인할 수 있다.

    > pip list
    …중략…
    cx-Freeze (5.0)
    …후략…

 

카테고리:Python

Windows에서 wxPython-Phoenix 사용시 DLL load failed 오류가 발생하는 경우 해결 방법

4월 19, 2016 3개의 댓글

문제 발생 환경 정보

  • Windows 8.1 K
  • Python 3.5.1 (32bit)
  • wxPython-Phoenix 3.0.3.dev1964+f780b21 (32bit)

wxPython-Phoenix를 설치하고 sample source를 작성하여 실행했더니 다음과 같은 오류가 발생하였다.

C:\Users\someone\Project\Nuri\InvoiceApp>python main.py
Traceback (most recent call last):
File “main.py”, line 3, in <module>
import wx
File “C:\Users\someone\Python3_5_1\lib\site-packages\wx\__init__.py”, line 17, in
<module>
from wx.core import *
File “C:\Users\someone\Python3_5_1\lib\site-packages\wx\core.py”, line 6, in <mod
ule>
from ._core import *
ImportError: DLL load failed: 지정된 모듈을 찾을 수 없습니다.

지정된 모듈을 찾다 실패했다는 내용인데 debugger를 봐도 wx\core.py에서 오류가 발생했다는 message외에는 도움이 될만한 내용을 찾지 못했다.

혹시나해서 wxPython-Phoenix snapshot page에서 다른 version을 3,4개 정도 설치해봤지만 모두 동일한 결과만 나올뿐이었다.

구글링도중 단서가 될만한 단어를 발견했다.

MSVCP140.DLL

좀 더 찾아가 보니 wxPython-users group에서 Microsoft Visual C++ Redistributable package 최신 version을 설치했더니 해결되었다는 글을 발견하였다.

Microsoft download center에서 최신 version인 Visual Studio 2015용 Visual C++ 재배포 가능 패키지를 download하여 설치해보았다.
현재 python을 32bit를 사용중에 있으므로 재배포 file중 vc_redist.x86.exe만 먼저 설치하고 sample source를 실행해 보았더니 문제 없이 실행되었다.

만약 사용중인 python version이 다르다면 최신 Visual C++ download 지원 page를 참고하여 설치하면 된다.

추가적으로 python 3.5의 what’s new 문서를 보니 Windows 개선사항에 보면 Microsoft Visual C++ 14.0을 사용해 build했다는 언급이 있다.

카테고리:Python

Windows에서 wxPython Phoenix 설치하기

4월 18, 2016 1개의 댓글

Windows에서 pip가 기본 내장된 Python을 설치하였다면 기본적으로는 Mac OS X에서 wxPython Phoenix 설치하기와 동일하게 진행하면 된다.
pip는 Python 2.7.9이상 혹은 Python 3.4이상에서 기본으로 포함되어 있다.

그런데 문제가 발생했다.
Python download page에서 python-3.5.1.exe를 다운받아 설치한 후 pip를 이용해 wxPython Phoenix를 설치하던 중 다음과 같은 error message를 만났다.

…전략…
Running command: build_wx
Command ‘”c:\users\someone\python3_5_1\python.exe” -c “import distutils.msvc9compiler as msvc; mc = msvc.MSVCCompiler(); mc.initialize(); print(mc.cc)”‘ failed with exit code 1.
Trackback (most recent call last):
File “<String>”, line 1, in <Module>
File “c:\users\someone\python3_5_1\lib\distutils\msvc9compiler.py”, line 374,in initialize
vc_env = query_vcvarsall(VERSION, plat_spec)
…중략…
You are using pip version 7.1.2, however version 8.1.1 is available.
You should consider upgrading via the `python -m pip install --upgrade pip` command.

역시나 친절한 error message다. 시키는 대로 pip를 upgrade하였다.

python -m pip install --upgrade pip

Successfully installed pip-8.1.1이라는 message가 뜬 후 다시 Phoenix를 설치해 보았다.

pip install --upgrade --trusted-host wxpyt
hon.org --pre -f http://wxpython.org/Phoenix/snapshot-builds/ wxPython_Phoenix

역시나 다음과 같은 message를 보여주며 설치 완료되었다.

Collecting wxPython-Phoenix
Downloading http://wxpython.org/Phoenix/snapshot-builds/wxPython_Phoenix-3.0.3
.dev1964+f780b21-cp35-cp35m-win32.whl (11.3MB)
100% |################################| 11.3MB 3.3MB/s
Installing collected packages: wxPython-Phoenix
Successfully installed wxPython-Phoenix-3.0.3.dev1964+f780b21

카테고리:Python

Mac OS X에서 wxPython Phoenix 설치하기

4월 11, 2016 1개의 댓글

현재(2016-04-11)까지는 wxPython-Phoenix는 snapshot build만 제공을 하고 있어
pip install wxpython과 같은 식으로 설치가 되진 않는다.

wxPython의 wiki페이지에 보면 다양한 설치방법이 있는데 이 중에서 pip를 사용하여 설치하는 방법을 공유하고자 한다.

pip install --upgrade --trusted-host wxpython.org --pre -f http://wxpython.org/Phoenix/snapshot-builds/ wxPython_Phoenix

다음과 같은 메시지가 출력되면서 설치가 된다.

Collecting wxPython-Phoenix
Downloading http://wxpython.org/Phoenix/snapshot-builds/wxPython_Phoenix-3.0.3.dev1964+f780b21-cp35-cp35m-macosx_10_6_intel.whl (29.7MB)
100% |████████████████████████████████| 29.7MB 3.1MB/s
Installing collected packages: wxPython-Phoenix
Successfully installed wxPython-Phoenix-3.0.3.dev1964+f780b21

그런데 설치가 완료되어 간단하게 빈 window를 띄우는 sample을 작성하여 실행해보니 다음과 같은 메시지가 출력되며 실행되지 않았다.

This program needs access to the screen.
Please run with a Framework build of python, and only when you are logged in on the main display of your Mac.

구글링을 해서 찾아보니 다양한 해결 방안을 제시하고 있었지만 가장 간단한 방법으로 해결하였다.

env PYTHON_CONFIGURE_OPTS=”--enable-framework” pyenv install 3.5.1

python 3.5.1을  –enable-framework option을 주어 재설치하게되니 window가 정상적으로 실행되었다.

카테고리:Python

Mac OS X에서 pyenv install 3.5.1 실행시 definition not found 오류 해결방법

4월 4, 2016 댓글 남기기

Mac OS X에서 python 3.5.1을 사용하기 위해 pyenv로 설치하려 시도 하였다.

pyenv install 3.5.1

설치가 잘 될거라고 기대하고 있었는데 다음과 같은 error가 발생되었다.

python-build: definition not found: 3.5.1

See all available versions with `pyenv install --list`.

If the version you need is missing, try upgrading pyenv:

cd /Users/imac/.pyenv/plugins/python-build/../.. && git pull && cd –

error message에 해결방법이 잘 설명되어 있지만 혹시나 하고 pyenv install --list 명령을 실행하여설치 가능한 버전을 확인해 보았다.

Available versions:
2.1.3
2.2.3
… 중략 …
3.5.0
3.5-dev
3.6-dev
… 후략 …

3.5.1이 없으니 error message에서 언급한 것 처럼 pyenv를 upgrade해보았다.
upgrade는 pyenv 사이트의 upgrade 항목을 참고하였다.

cd ~/.pyenv
git pull

다시 설치 가능한 버전을 확인해 보니 3.5.1이 있다.

Available versions:
2.1.3
2.2.3
… 중략 …
3.5-dev
3.5.1
3.6-dev
… 후략 …

이제 원래 하려던 3.5.1을 설치 할 수 있게 되었다.

카테고리:Python

site내 content가 가변길이인 경우 footer 하단 처리 방법

3월 16, 2016 2개의 댓글

site내의 content의 height가 가변길이인 경우 footer의 위치를 깔끔하게 처리하고 싶었다.
원하는 구성은 다음과 같았다.

  • content의 height가 browser의 height보다 짧은 경우 footer는 browser 하단에 위치
  • content의 height가 browser의 height보다 긴 경우 footer는 content 하단에 위치

우선 간단한 html을 구성하였다.

<!DOCTYPE html>
<html>
<head>
<title>test</title>
</head>
<body>
<div class=”wrap”>
<header>Header</header>
<section>
<div>
<ol>
<li>Content</li>
<li>Content</li>
<li>Content</li>
<li>Content</li>
<li>Content</li>
<li>Content</li>
<li>Content</li>
<li>Content</li>
<li>Content</li>
<li>Content</li>
</ol>
</div>
</section>
<footer>Footer</footer>
</div>
</bodY>
</html>

기본적으로 상단(header), content(section), 하단(footer)로 구성하였다.
결과부터 보자면 다음과 같다.

browser_gt_content

content의 height < browser의 height인 경우

 

 

content_gt_browser_1

content의 height > browser의 height인 경우

content_gt_browser_2

scroll을 내려보면 content 하단에 붙어있는 것을 확인할 수 있다.

 

원했던 구성이 깔끔하게 처리되었다.
(content의 height가 browser의 height보다 짧은 경우에는 하얀 여백이 보여지게 되는데 이부분은 div.wrap의 background-color를 주는 식으로 해결이 가능하다.)

이제 layout을 구성한 css를 확인해보면 다음과 같다.

* {
box-sizing: border-box;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
}
html {
height: 100%;
}
body {
margin: 0;
height: 100%;
}
.wrap {
min-height: 100%;
position: relative;
padding-bottom: 19px; /* footer height */
}
header {
background-color: #EFEFEF;
}
section {
background-color: #AFAFAF;
}
ol {
margin: 0;
}
footer {
position: absolute;
bottom: 0;
left: 0;
right: 0;
color: white;
background-color: #333333;
}

기본적인 개념은 다음과 같다.

  • html, body의 height를 100%로 설정
  • content의 height가 browser의 height보다 짧은 경우를 위해  div.wrap class에 min-height: 100% 설정
  • footer는 position: absolute로 하여 bottom: 0에 고정
  • footer를 content기준으로 위치를 잡기 위해 div.wrap class를 position: relative로 설정
  • footer가 content(section)과 겹치지 않게 하기위해 div.wrap에 footer높이 만큼 padding-bottom을 지정
  • padding-bottom에 지정한 값을 영역값으로 잡기 위해 box-sizing을 border-box로 지정

이 방법의 경우의 전제조건은 footer의 height값이 고정이어야 한다는 것인데 footer의 height값이 가변인 경우에는 좀 더 고민을 해봐야 할 것 같다.
추후 관련 issue가 발생되면 추가로 post할 예정이다.

카테고리:CSS

jQuery serialize(), serializeArray() 사용시 동적으로 추가한 element가 빠지는 현상

3월 3, 2016 댓글 남기기

여러건의 정보를 넣기 위해 동적으로 input element를 생성하고 jQuery.form plugin의 ajaxSubmit()을 사용해 DB에 자료를 저장하도록 했다.
그런데 동적으로 추가된 input element의 정보가 DB에 저장이 되지 않는 증상이 발생되었다.
chrome developer tools의 Network 부분을 보니 request시 아예 넘어가지 않았다.
여러번의 삽질끝에 힌트가 되는 다음 소스를 찾았다.

jquery.form.js

$.fieldValue = function(el, successful) {
…생략…
if (successful && (!n || el.disabled || t==’reset’ || t=’button’ ||
(t == ‘checkbox’ || t == ‘radio’) && !el.checked ||
(t == ‘submit’ || t == ‘image’) && el.form && el.form.clk != el ||
tag == ‘select’ && el.selectedIndex == -1)) {
return null;
}
…생략…
}

jQuery.form plugin은 ajaxSubmit()을 하기 전에 form안의 element들의 value를 추출하는데
이때 위의 소스에 있는 조건에 맞지 않으면 value를 추출하지 않는다.
“jQuery serialize(), serializeArray()시 input element의 value가 추출되지 않는다”라는 질문들에 대해 대부분의 답변은 바로 저 위의 조건을 맞추라는 것이다.
보통은 name attribute가 있어야 하니 추가해라라는 답변이 대부분이긴 하다.

그런데 이번 상황에서는 좀 다른 문제가 발생했다.
소스 중간의 el.form 이 문제였다.
동적으로 추가된 input element의 form property값이 null이어서 value가 추출되지 않았던 것이다.
문제가 있던 소스는 다음과 같다.

<table>
<form name=”frm” id=”regForm”>
<tbody>
<tr>
<td><input type=”text” name=”some1″ value=””/></td>
<td><input type=”text” name=”some2″ value=””/></td>
</tr>
<tr> <!– 동적으로 추가된 tr –>
<td><input type=”text” name=”some1″ value=””/></td>
<td><input type=”text” name=”some2″ value=””/></td>
</tr>
</tbody>
</form>
</table>

console에서 form property값을 찍어본 결과는 다음과 같다.

$(‘input[name=some1]’).eq(0)[0].form
결과 : <form name=”frm” id=”regForm”></form>

$(‘input[name=some1]’).eq(1)[0].form
결과 : null

chrome의 developer tools에서 Elements를 확인해 보니 소스와는 달리 rendering이 되어있었다.

<table>
<form name=”frm” id=”regForm”></form>
<tbody>
<tr>
<td><input type=”text” name=”some1″ value=””/></td>
<td><input type=”text” name=”some2″ value=””/></td>
</tr>
<tr> <!– 동적으로 추가된 tr –>
<td><input type=”text” name=”some1″ value=””/></td>
<td><input type=”text” name=”some2″ value=””/></td>
</tr>
</tbody>
</table>

form tag부분이 한 줄로 붙어버려있다.
특이한 것은 console에서 form property를 찍어보았듯이 동적으로 추가하지 않은 부분의 input element는 정상적으로 value가 추출된다는 것이다.
여튼 이상황을 해결하기 위해 form tag의 위치를 well-formed가 되도록 수정하였다.

<form name=”frm” id=”regForm”>
<table>
<tbody>
<tr>
<td><input type=”text” name=”some1″ value=””/></td>
<td><input type=”text” name=”some2″ value=””/></td>
</tr>
<tr> <!– 동적으로 추가된 tr –>
<td><input type=”text” name=”some1″ value=””/></td>
<td><input type=”text” name=”some2″ value=””/></td>
</tr>
</tbody>
</table>
</form>

console에서 input element의 form property를 다시 찍어보니 정상적으로 출력되었고
value도 정상적으로 추출되었다.
물론 chrome의 developer tools에서 Elements를 확인해도 의도한대로 form tag하위에 table이 들어가 있다.

카테고리:JavaScript