Category: Python

[error]CreateProcess error=2, The system cannot find the file specified in PyCharm

Error Detail

When I try to run python in PyCharm. The error occurred as below. What is venv\Scripts\python.exe?

Error running 'easy_keymaps_ui': Cannot run program "C:\Users\<USER_NAME>\source\test\venv\Scripts\python.exe" (in directory "C:\Users\<USER_NAME>\source\test"): CreateProcess error=2, The system cannot find the file specified

Environment

Windows 10
PyCharm 2020.3
Python 3.8

Cause

The python specified to use as interpreter in PyCharm cannot be found. In my case, the specified python is python that is bundled to the deleted virtual env of PyCharm project.
Check “Configure a virtual environment” for details about virtual env of PyCharm.

Solution

Change the python to use

Right click the program to run. And click “Modify Run Configuratuib…”

Select valid interpreter and click ”OK”.

How to remove and add python interpreters to the project

Open “File > Settings > Python Interpreter”. Click the gear icon and click “Show All” button.

Click “-” button to delete invalid Python.

And click “+” button to add new valid python to use to run python program. I selected my local system python.

How To Run Python Script When Blender Starts

GOAL

To run Python script when Blender starts only once or every time.

Environment

Blender 2.83
Windows 10

Method

I created a simple Python script “Documents\blenderPython\test\spheres.py” to add spheres as below

import bpy
for i in range(3):
    bpy.ops.mesh.primitive_uv_sphere_add(radius=1, location=((i-1)*3, 0, 3))

Only once

Start Blender with command

Start blender in command prompt with an argument -P or –python.
Reference: Python Options in Blender 2.91 Manual

(more…)

How To Get Attributes Of Object In Python

This is just a tips.

GOAL

To get the list of attributes of an object in Python

Environment

Python 3.7.4

Method

Use built-in function dir([object]) method as below.

dict1 = {"a":1, "b":2}
print(dir(dict1))
# output => ['__class__', '__contains__', '__delattr__', ... , 'setdefault', 'update', 'values']

dir() can takes not only variable but also any objects such as ‘type’ itself.

print(dir(dict))
# output is the same as print(dir(dict1)) above 

dir() can be used for user-defined class, too.

class User:
    number = 0
    def __init__(self, name, age=0):
        self.name = name
        self.age = 0
        self.addNum()
    def profile(self):
        print("Name:"+self.name, " Age:"+self.age)
    @classmethod
    def addNum(cls):
        cls.number += 1g

user1 = User("John", 20)
print(dir(user1))
# output => ['__class__', '__delattr__', '__dict__', ... , 'addNum', 'age', 'name', 'number', 'profile']

dir([object]) function return the list of only the object’s attributes. So the list returned by dir(User) includes class variables “number” but don’t include instance variables “name” and “age”.

 class User:
    number = 0
    def __init__(self, name, age=0):
        self.name = name
        self.age = age
        self.addNum()
    def isAdult(self):
        if 18 <= self.age:
            return True
        else:
            return False
    def profile(self):
        print("Name:"+self.name, " Age:"+self.age)
    @classmethod
    def addNum(cls):
        cls.number += 1

print(dir(User))
# output => ['__class__', '__delattr__', '__dict__', ... , 'addNum', 'number', 'profile']

If dir() takes no argument, it returns the list of names in the current local scope.

user1 = User("John", 20)
num1 = 10
dict1 = {"a":1, "b":2}
print(dir())
# output => ['User', '__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'dict1', 'num1', 'user1']

Appendix

Module “inspect” is also used for getting information of objects as below.

import inspect
user1 = User("John", 20)
print(inspect.getmembers(user1))
# getmembers returns the pairs of (attribute, its value)
# output => [('__class__', <class '__main__.User'>), ('__delattr__', <method-wrapper '__delattr__' of User object at 0x000002B8A1BBAEB0>), ('__dict__', {'name': 'John', 'age': 20}), ... , ('name', 'John'), ('number', 1), ('profile', <bound method User.profile of <__main__.User object at 0x000002B8A1BBAEB0>>)]

Function vars([object]) only return __dict__ attributes of the object that is the dict of (variables, value).

user1 = User("John", 20)
print(vars(user1))
# output => {'name': 'John', 'age': 20}

What is gettext

Gettext is an library for internationalization(I18N) and localization(L10N).

GOAL

To understand what is gettext and how to use it.

What is gettext

gettext is a library for translation in software. It can make sentences in the software multilingual.

pot file

Pot file is the template file for translation. Sentences to translate are defined in it.

po file

Translations of the sentences defined in pot file in each language are listed in po file.

mo file

mo file is binary file generated from po file.

domain

Domain is the identifier with that gettext module find the template for traslation.

How to use gettext in Python

Use gettext module.

Method 1. GNU gettext API

This method can work only in linux and unix because it uses the environment variables LANGUAGE, LC_ALL, LC_MESSAGES.
Reference: GNU gettext API

1. Create source file “gettext_test.py”

The argument ‘myapplication’ is domain and ‘locale_dir’ is the directory where mo file is.

import gettext

gettext.bindtextdomain('myapplication', 'locale_dir')
gettext.textdomain('myapplication')
_ = gettext.gettext
print (_('Hello World!'))

2. Create <domain>.pot file with pygettext.py that is in Python<version>\Tools\i18n directory. The pot file myapplication.pot will be generated in the directory “locale_dir”.

python Python<version>\Tools\i18n\pygettext.py -d myapplication -p locale_dir gettext_test.py

The following is generated myapplication.pot.

# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR ORGANIZATION
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.

msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2020-07-20 01:35+0900\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=cp932\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: pygettext.py 1.5\n"

#: gettext_test.py:7
msgid "Hello World!"
msgstr ""

3. Create po file and put it in the language directory.

Change the charset into utf-8, input the translation and save it chadnged myapplication.po. In my case, the Japanese “こんにちは世界!” that means “Hello World!” is put in msgstr.

# SOME DESCRIPTIVE TITLE.
.
.
.
"Content-Type: text/plain; charset=utf-8\n"
.
.
.
#: gettext_test.py:7
msgid "Hello World!"
msgstr "こんにちは世界!"

Put the chadnged myapplication.po in the <directory_name>/language/LC_MESSAGES. The language is <language codes>_<country codes>. I put it in locale_dir/ja_JP/LC_MESSAGES.
The list of language code and country code: ISO-3166 Country Codes and ISO-639 Language Codes

4. Generate mo file from po file with Python<version>\Tools\i18n\msgfmt.py

python Python<version>\Tools\i18n\msgfmt.py myapplication.po

This image is the file construction.

5. Execute gettext_test.py

python gettext_test.py
こんにちは世界!

Method 2. Class-based API

This can be used in linux, unix and Windows.
Reference: Class-based API

1. Create source file “gettext_test.py”

Use translation(). The argument ‘myapplication’ is domain and ‘locale_dir’ is the directory where mo file is.

import os
import gettext

_ = gettext.translation(
    domain='myapplication',
    localedir = 'locale_dir',
    languages=['ja_JP'], 
    fallback=True).gettext

print (_('Hello World!'))

The rest processes are same as “Method 1. GNU gettext API” above.

2. Create <domain>.pot file with pygettext.py

3. Create po file and put it in the language directory <directory_name>/language/LC_MESSAGES.

4. Generate mo file from po file with Python<version>\Tools\i18n\msgfmt.py

5. Execute gettext_test.py

python gettext_test.py
こんにちは世界!

[Tips] Where Is Python Module Directory?

GOAL

To find the directory where python libraries are.

Method

Use sys.path

You can get the list of module search paths. Find the directory you’d like from the list.

>python
Python 3.8.6
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.path
---The list of module search paths---

Appendix

You can find the directory where python.exe is by using “where” command.

>where python
C:\Users\<USER_NAME>\AppData\Local\Microsoft\WindowsApps\python.exe
C:\Python27\python.exe

Search all files with Python

GOAL

To trace all files in the directory with Python

Environment

WIndows 10
Python 3.8.6

Method

Use glob.glob(path +’/**’, recursive=True)

import glob
import os

path = "C:\\path\\direcotry"

files = glob.glob(path +'/**', recursive=True)
for file_item in files:
    print(file_item)

* If you don’t add recursive=True, only the directory defined as “path” is searched.

UnicodeDecodeError: ‘cp932’ codec can’t decode byte 0x99 in position ~ : illegal multibyte sequence

Problem

When I open the file in Python, the error “UnicodeDecodeError: ‘cp932’ codec can’t decode byte 0x99 in position ~ : illegal multibyte sequence” occurred.

The code is as below.

path = 'wordpress/wp-admin/about.php'

with open(path) as f:
            lines = f.readlines()
            print(lines)

Environment

Windows 10
Python 3.8.6

The cause of this problem

The character code ‘cp932’ is Microsoft Cade page 932(Shift_JIS). And ‘0x99’ is the number of 1byte represented by hexadecimal. This error occurs when the character code used for decoding the file does not match the character code of the file.

Solution

Solution 1. Use encoding option argument

If you know the coding of the file, you can specify it with option argument of open() function.

with open(path, encoding = "utf_8") as f:
    lines = f.readlines()
    print(lines)

Solution 2. Use try and except

If you’d like to use a few character coding and ignore files of other character coding.

try:
    with open(path, encoding = "shift_jis") as f:
        lines = f.readlines()
        print(lines)
except:
    pass
try:
    with open(path, encoding = "ascii") as f:
        lines = f.readlines()
        print(lines)
except:
    pass
try:
    with open(path, encoding = "utf_8") as f:
        lines = f.readlines()
        print(lines)
except:
    pass

Solution 3. Use chardet

Chardet is a module to detect the character encoding.

Install chardet with pip command.

> pip install chardet

Installing collected packages: chardet
....
Successfully installed chardet-3.0.4

You can get the character encoding by chardet.dect(<binary data>).

import chardet
path = 'wordpress/wp-admin/about.php'

with open(path, mode='rb') as f:
    binary = f.read()
    code = chardet.detect(binary)['encoding']
with open(path, encoding=code) as f:
    lines = f.readlines()
    print(lines)

Solution 4. Ignore errors by codec

You can ignore errors by using codec.open() and setting the option argument ‘errors’ ‘ignore’.

import codec
path = 'wordpress/wp-admin/about.php'

with codecs.open(path, 'r', 'utf-8', 'ignore') as f:
    lines = f.readlines()
    print(lines)

[Error]’unicodeescape’ codec can’t decode bytes

Problem

When I run the python code below, the error “SyntaxError: (unicode error) ‘unicodeescape’ codec can’t decode bytes in position 2-3” occurred.

import glob
import os

word = "single_post_title"
path = "C:\Users\USERNAME\Downloads\document"
files = glob.glob(path +'\**')
for f in files:
    print(f)

Environment

Windows10
Python 3.8.6

Cause of the error

The unicodeescape ‘\’ is used in path = “C:\Users\USERNAME\Downloads\document”. “\” is used as a part of escape sequences in Windows system.

Solution

Solution 1. Use “\\” to express “\” in string data

path = "C:\\Users\\USERNAME\\Downloads\\document"
files = glob.glob(path +'\\**')

Solution 2. Use “/” instead of “\”

path = "C:/Users/USERNAME/Downloads/document"
files = glob.glob(path +'/**')

How To Use Qt Designeer

GOAL

To understand what QtCreator is and how to use it.

What is Qt and PySide?

Qt is a cross-platform application framework with many modules providing services like network abstraction and XML handling, along with a very rich GUI package. Check the article “First PySide Application” for details of Qt and PySide.

What is Qt Designer?

Qt Designer is the Qt tool for designing and building GUIs with Qt Widgets. Qt Designer makes it easy to layout UI widgets with PySide.
Reference: Qt Designer Manual

How to use

Environment

Windows10
Python3.8.5
PySide2-5.15.1

Install and Start Qt Designer

1. Install PySide or PySide2

pip install PySide2
Collecting PySide2
  Downloading PySide2-5.15.1-5.15.1-cp35.cp36.cp37.cp38.cp39-none-win_amd64.whl (136.9 MB)
     |████████████████████████        | 101.6 MB 1.7 MB/s eta 0:00:22    
...
omitted
...
Successfully installed PySide2-5.15.1 shiboken2-5.15.1

Use pip3 if you need. When you use Python2, PySide2 can’t be installed by pip command, so please install python3 or use PySide.

2. Start designer.exe

Start PythonDir\site-packages\PySide2\designer.exe

You can find the directory “PySide2” by PySide2.__file__

import PySide2
print(PySide2.__file__)

Or you can find the python directory with the command below.

C: >where python

If you are using Python2, designer.exe exists in Python2\Lib\site-packages\PySide directory.

Create Dialog

1. Create a new form

When you start the designer.exe, the “New Form” window will open automatically. If not, click File > New

Select any template you like and click the button “Create”.

An empty untitled widget with “OK” and “Cancel” buttons will appear.

2 Put the widget on the empty Dialog

Drag & Drop any widget you like from “Widget Box” and put it into the empty Dialog. I created a dialog to export reduced object in DCC tool.

from Qt Designer

The construction of this form is the following.

And reform the widgets in main layout. Right-click on the form outside of the form Layout and click layout>Lay Out Vertically.

The widgets are arranged at even intervals in the main layout.

Set the default values and change settings of each property with “Property Editor.”

from Qt Designer

3. Connect the signals to the slots

In Qt Designer, you can connect the signal of the widget to the slot of another widget, in other words connect some widgets as input and output. In this case, Spin Box and Horizontal Slider should move in conjunction with each other.

Change the mode to edit signals/slots by clicking Form>Edit Signals/Slots.

Drag & drop from Spin Box to Horizontal Slider.

The signal is valueChanged and the connected slot is setValue.

In contrast, drag & drop from Horizontal Slider to Spin Box and connect them in the same way.

4. Preview

Preview the form you created by Form>Preview… and check if it works well.

5. Save the UI as Designer UI files (.ui)

Save the dialog you created as “reduced_export.ui”.

Load .ui from Python file

You can load .ui file you created from python file.

Run the program below and the dialog you created will be displayed.

# -*- coding: utf-8 -*
import sys
from PySide2 import QtWidgets
from PySide2.QtUiTools import QUiLoader

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    loader = QUiLoader()
    widget = loader.load('reduced_export.ui', None)
    if not widget:
        print(loader.errorString())
        sys.exit(-1)
    widget.show()
    sys.exit(app.exec_())

Or define ExportUI class that inherits QMainWindow.

class ExportUI(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(ExportUI, self).__init__(parent)
        loader = QUiLoader()
        self.ui = loader.load('reduced_export.ui')
        if not self.ui:
            print(loader.errorString())
            sys.exit(-1)
        print("OPEN")
    def getUi(self):
        return self.ui

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    exportUi = ExportUI()
    widget = exportUi.getUi()
    widget.show()
    sys.exit(app.exec_())

Connect functions you defined to the widgets

When the “OK” button is clicked, or the buttonBox widget is accepted, call the function export() that is the function to export the selected object in DCC tools. You can connect them by using “self.ui.buttonBox.accepted.connect(self.export)”.

In this example the function export() is omitted.

# -*- coding: utf-8 -*
import sys
from PySide2 import QtWidgets
from PySide2.QtUiTools import QUiLoader

def exportObj(name, extension, detail, options):
    # omitted the function to export object
    ext = 'fbx' if extension else 'obj' 
    print(f"exported {name}.{ext} with {detail}% detail and option {options}.")

class ExportUI(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(ExportUI, self).__init__(parent)
        loader = QUiLoader()
        self.ui = loader.load('reduced_export.ui')
        if not self.ui:
            print(loader.errorString())
            sys.exit(-1)
        print("OPEN")
        self.ui.buttonBox.accepted.connect(self.export)

    def getUi(self):
        return self.ui

    def export(self):
        name = self.ui.nameLineEdit.text()
        extension = 0 if self.ui.radioButton.toggle() else 1
        detail = self.ui.horizontalSlider.value()
        options = [self.ui.checkBox.isChecked(), self.ui.checkBox_2.isChecked() ,self.ui.checkBox_3.isChecked()]
        exportObj(name, extension, detail, options)

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    exportUi = ExportUI()
    widget = exportUi.getUi()
    widget.show()
    sys.exit(app.exec_())

You should know the classes and functions to get values such as QnameLineEdit.text() or QRadioButton.isChecked(). And you can see the class and the name of each widget in Property Editor of Qt Designer.

Run

Run the python code above and set the values on the displayed dialog.

Click the “OK” button. Then the message below will be displayed on the console.

exported HumanModel.fbx with 66% detail and option [False, True, True].

Other tools for Qt programming

QtCreator

QtCreator is C++ IDE for development with Qt. It has an editor with useful functions, navigation tools, GUI tools for UI design and so on.
Reference: Qt Creator Manual

Qt Linguist

Qt Linguist is a tool for translating Qt C++ and Qt Quick applications into local languages.
Reference: Qt Linguist Manual

Qt Assistant

Qt Assistant is a tool for viewing on-line documentation for Qt programming. 
Reference: Qt Assistant Manual