Closed hash3liZer closed 4 months ago
Well, blessed is thread safe, I have successfully used it in a threaded terminal server project serving each client ip it’s own output (telnet 1984.ws a public server), It hasn’t any thing to do with threads, just that the file descriptor (sys.stdout) is shared. If you removed the threads and used asyncio, for example, it would have the same problem.
https://ejrh.wordpress.com/2011/09/18/output-synchronisation-in-python/
in blessed docs we say, “calls to location() may not be nested”, calling it twice on the same file descriptor is an example of “nesting”, the use of threads just makes it appear logically separate, I’m sorry this wasn’t clear, maybe we can add some documentation
These context managers have the side effect of printing hidden terminal sequences to the screen that are interpreted by the terminal, it can only handle one location sequence
Well, i guess that explains the messed up terminal. I found a quick solution though by putting all the location
related statements under the same class and used a class variable to determine if another location
context wrapper is being used somewhere. If it is, then while True: pass
. Otherwise, go on.
I think adding that to the documentation would be very helpful. I don't know if i should close this right now or not though i found my answer. On to you from here.
Also, one more question, i had. It's a different one. Anyways, i am asking here. When i compile my script pyinstaller --noconsole
option with blessed being used in the script, i get this error:
Failed to execute script
Without creating the terminal instance, i.e. term = Terminal()
, it works all fine.
Sorry I missed the PyInstaller issue, I haven't used or contributed to PyInstaller in over 15 years, but if you can reduce your problem to a simple set of files I'm sure PyInstaller or StackOverflow can help. I was able to make an executable using blessed with PyInstaller On MacOS using 3.12 without any issue.
file cli.spec
,
cli.spec
# -*- mode: python -*-
block_cipher = None
a = Analysis(['cli/__main__.py'],
pathex=[], binaries=[], datas=[], hiddenimports=[], hookspath=[], runtime_hooks=[],
excludes=[], win_no_prefer_redirects=False, win_private_assemblies=False,
cipher=block_cipher, noarchive=False)
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
exe = EXE(pyz, a.scripts, [], exclude_binaries=True, name='cli', debug=False, bootloader_ignore_signals=False,
strip=False, upx=True, console=True )
coll = COLLECT(exe, a.binaries, a.zipfiles, a.datas, strip=False, upx=True, name='cli')
file setup.py
,
from setuptools import setup
setup(
name="cli", version="1.0.0", description="", license="MIT",
packages=["cli"], include_package_data=True,
install_requires=["blessed"], entry_points={"console_scripts": ["cli=cli.__main__:main"]},
)
file cli/__main__.py
,
import blessed
def main():
term = blessed.Terminal()
print(term.blue_on_white("hello, world"))
if __name__ == '__main__':
main()
And this executed just fine, so I will close this issue
First of all, it's really a great library and kudos to the development. I've integrated this library in a project of mine where multiple threads are printing on the terminal at the same time. Consider these two functions:
Now, if you run these functions simulataneously using threads (a couple times to make sure), you will see sometimes each bar is overlapped on the other bar. Which means that the functions being called are not thread safe. And calling multiple lines at the same time will mess the output.