logtail / logtail-python

Better Stack Python client
https://betterstack.com/logs
Other
36 stars 10 forks source link

Exception in PyInstaller packaged app #16

Open z4none opened 1 year ago

z4none commented 1 year ago

I am using logtail in a PyInstaller packaged project on Windows, my exe is saved on drive D: I create the LogtailHandler with raise_exceptions=True, when I call logger.info I got these exception:

pathname='main.py' has_main_module=True pathname='main.py' __main__.__file__='C:\\Users\\zi\\AppData\\Local\\Temp\\_MEI61722\\main.py'
Traceback (most recent call last):
  File "main.py", line 647, in <module>
  File "main.py", line 641, in main
  File "main.py", line 161, in __init__
  File "logging\__init__.py", line 1446, in info
  File "logging\__init__.py", line 1589, in _log
  File "logging\__init__.py", line 1599, in handle
  File "logging\__init__.py", line 1661, in callHandlers
  File "logging\__init__.py", line 952, in handle
  File "logtail\handler.py", line 73, in emit
  File "logtail\handler.py", line 63, in emit
  File "logtail\frame.py", line 25, in create_frame
  File "logtail\frame.py", line 70, in _relative_to_main_module_if_possible
  File "logtail\frame.py", line 73, in _relative_to_main_module
  File "ntpath.py", line 703, in relpath
ValueError: path is on mount 'D:', start on mount 'C:'
[33228] Failed to execute script 'main' due to unhandled exception!

It appears that the exe was launched from another drive than the one py file was unpacked from, so that logtail cant get the relative path.

versions windows: 10 python: 3.9 logtail-python: 0.2.6 pyinstaller: 5.13.0

curusarn commented 1 year ago

Hey @z4none!

Thank you for reaching out!

We have seen this issue happen when your System drive is C:/ while your Python is on D:/. You should be able to get rid of the error by specifying the exact location:

import logging
from logtail import LogtailHandler

handler = LogtailHandler(source_token='your_token', log_file_path='C:/path_to_log_file')
logger = logging.getLogger(__name__)
logger.addHandler(handler)

logger.info("Hello, world!")

Let me know if this solves the issue. 🙏

Thanks again for raising this.

z4none commented 1 year ago

I have tested the code above, but it failed with an exception.

Traceback (most recent call last):
  File "D:\workspace\logtail-test\main.py", line 6, in <module>
    handler = LogtailHandler(source_token='your_token', log_file_path='C:/path_to_log_file')
TypeError: __init__() got an unexpected keyword argument 'log_file_path'

I created a minimal script to reproduce the exception in _relative_to_main_module.

# main.py
import logging
from logtail import LogtailHandler

handler = LogtailHandler(source_token='my token', raise_exceptions=True)
logger = logging.getLogger(__name__)
logger.addHandler(handler)
logger.setLevel(logging.INFO)
logger.info(f"Hello")

If i run python main.py or build with pyInstaller pyinstaller main.py then run main.exe it works with no problem. But if I use pyInstaller to build it into a single exe pyinstaller -F main.py then run main.exe, it will fail

Traceback (most recent call last):
  File "main.py", line 19, in <module>
  File "logging\__init__.py", line 1446, in info
  File "logging\__init__.py", line 1589, in _log
  File "logging\__init__.py", line 1599, in handle
  File "logging\__init__.py", line 1661, in callHandlers
  File "logging\__init__.py", line 952, in handle
  File "logtail\handler.py", line 72, in emit
  File "logtail\handler.py", line 62, in emit
  File "logtail\frame.py", line 25, in create_frame
  File "logtail\frame.py", line 69, in _relative_to_main_module_if_possible
  File "logtail\frame.py", line 72, in _relative_to_main_module
  File "ntpath.py", line 703, in relpath
ValueError: path is on mount 'D:', start on mount 'C:'
[22108] Failed to execute script 'main' due to unhandled exception!

My current solution is to modify _relative_to_main_module_if_possible function in logtail\frame.py

def _relative_to_main_module_if_possible(pathname):
    has_main_module = hasattr(__main__, '__file__')
    try:
        return _relative_to_main_module(pathname) if has_main_module else pathname
    except:
        return pathname